<commit_before>
module.exports = errorHandler

var cbCalled = false
  , log = require("npmlog")
  , npm = require("../npm.js")
  , rm = require("rimraf")
  , itWorked = false
  , path = require("path")
  , wroteLogFile = false
  , exitCode = 0

process.on("exit", function (code) {
  // console.error("exit", code)
  if (!npm.config || !npm.config.loaded) return
  if (code) itWorked = false
  if (itWorked) log.info("ok")
  else {
    if (!cbCalled) {
      log.error("", "cb() never called!")
    }

    if (wroteLogFile) {
      // just a line break
      if (log.levels[log.level] <= log.levels.error) console.error("")

      log.error("",
                ["Please include the following file with any support request:"
                ,"    " + path.resolve("npm-debug.log")
                ].join("\n"))
      wroteLogFile = false
    }
    if (code) {
      log.error("code", code)
    }
  }

  var doExit = npm.config.get("_exit")
  if (doExit) {
    // actually exit.
    if (exitCode === 0 && !itWorked) {
      exitCode = 1
    }
    if (exitCode !== 0) process.exit(exitCode)
  } else {
    itWorked = false // ready for next exit
  }
})

function exit (code, noLog) {
  exitCode = exitCode || process.exitCode || code

  var doExit = npm.config ? npm.config.get("_exit") : true
  log.verbose("exit", [code, doExit])
  if (log.level === "silent") noLog = true

  if (code && !noLog) writeLogFile(reallyExit)
  else rm("npm-debug.log", function () { rm(npm.tmp, reallyExit) })

  function reallyExit() {
    // truncate once it's been written.
    log.record.length = 0

    itWorked = !code

    // just emit a fake exit event.
    // if we're really exiting, then let it exit on its own, so that
    // in-process stuff can finish or clean up first.
    if (!doExit) process.emit("exit", code)
    npm.spinner.stop()
  }
}

function errorHandler (er) {
  // console.error("errorHandler", er)
  if (!npm.config || !npm.config.loaded) {
    // logging won't work unless we pretend that it's ready
    er = er || new Error("Exit prior to config file resolving.")
    console.error(er.stack || er.message)
  }

  if (cbCalled) {
    er = er || new Error("Callback called more than once.")
  }

  cbCalled = true
  if (!er) return exit(0)
  if (typeof er === "string") {
    log.error("", er)
    return exit(1, true)
  } else if (!(er instanceof Error)) {
    log.error("weird error", er)
    return exit(1, true)
  }

  var m = er.code || er.message.match(/^(?:Error: )?(E[A-Z]+)/)
  if (m && !er.code) er.code = m

  ; [ "type"
    , "fstream_path"
    , "fstream_unc_path"
    , "fstream_type"
    , "fstream_class"
    , "fstream_finish_call"
    , "fstream_linkpath"
    , "stack"
    , "fstream_stack"
    , "statusCode"
    , "pkgid"
    ].forEach(function (k) {
      var v = er[k]
      if (!v) return
      if (k === "fstream_stack") v = v.join("\n")
      log.verbose(k, v)
    })

  log.verbose("cwd", process.cwd())

  var os = require("os")
  // log.error("System", os.type() + " " + os.release())
  // log.error("command", process.argv.map(JSON.stringify).join(" "))
  // log.error("node -v", process.version)
  // log.error("npm -v", npm.version)
  log.error("", os.type() + " " + os.release())
  log.error("argv", process.argv.map(JSON.stringify).join(" "))
  log.error("node", process.version)
  log.error("npm ", "v" + npm.version)

  ; [ "file"
    , "path"
    , "code"
    , "errno"
    , "syscall"
    ].forEach(function (k) {
      var v = er[k]
      if (v) log.error(k, v)
    })

  // just a line break
  if (log.levels[log.level] <= log.levels.error) console.error("")

  switch (er.code) {
  case "ECONNREFUSED":
    log.error("", er)
    log.error("", ["\nIf you are behind a proxy, please make sure that the"
              ,"'proxy' config is set properly.  See: 'npm help config'"
              ].join("\n"))
    break

  case "EACCES":
  case "EPERM":
    log.error("", er)
    log.error("", ["\nPlease try running this command again as root/Administrator."
              ].join("\n"))
    break

  case "ELIFECYCLE":
    log.error("", er.message)
    log.error("", ["","Failed at the "+er.pkgid+" "+er.stage+" script."
              ,"This is most likely a problem with the "+er.pkgname+" package,"
              ,"not with npm itself."
              ,"Tell the author that this fails on your system:"
              ,"    "+er.script
              ,"You can get their info via:"
              ,"    npm owner ls "+er.pkgname
              ,"There is likely additional logging output above."
              ].join("\n"))
    break

  case "ENOGIT":
    log.error("", er.message)
    log.error("", ["","Failed using git."
              ,"This is most likely not a problem with npm itself."
              ,"Please check if you have git installed and in your PATH."
              ].join("\n"))
    break

  case "EJSONPARSE":
    log.error("", er.message)
    log.error("", "File: "+er.file)
    log.error("", ["Failed to parse package.json data."
              ,"package.json must be actual JSON, not just JavaScript."
              ,"","This is not a bug in npm."
              ,"Tell the package author to fix their package.json file."
              ].join("\n"), "JSON.parse")
    break

  // TODO(isaacs)
  // Add a special case here for E401 and E403 explaining auth issues?

  case "E404":
    var msg = [er.message]
    if (er.pkgid && er.pkgid !== "-") {
      msg.push("", "'"+er.pkgid+"' is not in the npm registry."
              ,"You should bug the author to publish it (or use the name yourself!)")
      if (er.parent) {
        msg.push("It was specified as a dependency of '"+er.parent+"'")
      }
      msg.push("\nNote that you can also install from a"
              ,"tarball, folder, http url, or git url.")
    }
    // There's no need to have 404 in the message as well.
    msg[0] = msg[0].replace(/^404\s+/, "")
    log.error("404", msg.join("\n"))
    break

  case "EPUBLISHCONFLICT":
    log.error("publish fail", ["Cannot publish over existing version."
              ,"Update the 'version' field in package.json and try again."
              ,""
              ,"To automatically increment version numbers, see:"
              ,"    npm help version"
              ].join("\n"))
    break

  case "EISGIT":
    log.error("git", [er.message
              ,"    "+er.path
              ,"Refusing to remove it. Update manually,"
              ,"or move it out of the way first."
              ].join("\n"))
    break

  case "ECYCLE":
    log.error("cycle", [er.message
              ,"While installing: "+er.pkgid
              ,"Found a pathological dependency case that npm cannot solve."
              ,"Please report this to the package author."
              ].join("\n"))
    break

  case "EBADPLATFORM":
    log.error("notsup", [er.message
              ,"Not compatible with your operating system or architecture: "+er.pkgid
              ,"Valid OS:    "+er.os.join(",")
              ,"Valid Arch:  "+er.cpu.join(",")
              ,"Actual OS:   "+process.platform
              ,"Actual Arch: "+process.arch
              ].join("\n"))
    break

  case "EEXIST":
    log.error([er.message
              ,"File exists: "+er.path
              ,"Move it away, and try again."].join("\n"))
    break

  case "ENEEDAUTH":
    log.error("need auth", [er.message
              ,"You need to authorize this machine using `npm adduser`"
              ].join("\n"))
    break

  case "EPEERINVALID":
    var peerErrors = Object.keys(er.peersDepending).map(function (peer) {
      return "Peer " + peer + " wants " + er.packageName + "@"
        + er.peersDepending[peer]
    })
    log.error("peerinvalid", [er.message].concat(peerErrors).join("\n"))
    break

  case "ECONNRESET":
  case "ENOTFOUND":
  case "ETIMEDOUT":
    log.error("network", [er.message
              ,"This is most likely not a problem with npm itself"
              ,"and is related to network connectivity."
              ,"In most cases you are behind a proxy or have bad network settings."
              ,"\nIf you are behind a proxy, please make sure that the"
              ,"'proxy' config is set properly.  See: 'npm help config'"
              ].join("\n"))
    break

  case "ENOPACKAGEJSON":
    log.error("package.json", [er.message
              ,"This is most likely not a problem with npm itself."
              ,"npm can't find a package.json file in your current directory."
              ].join("\n"))
    break

  case "ETARGET":
    log.error("notarget", [er.message
              ,"This is most likely not a problem with npm itself."
              ,"In most cases you or one of your dependencies are requesting"
              ,"a package version that doesn't exist."
              ].join("\n"))
    break

  case "ENOTSUP":
    if (er.required) {
      log.error("notsup", [er.message
                ,"Not compatible with your version of node/npm: "+er.pkgid
                ,"Required: "+JSON.stringify(er.required)
                ,"Actual:   "
                +JSON.stringify({npm:npm.version
                                ,node:npm.config.get("node-version")})
                ].join("\n"))
      break
    } // else passthrough

  case "ENOSPC":
    log.error("nospc", [er.message
              ,"This is most likely not a problem with npm itself"
              ,"and is related to insufficient space on your system."
              ].join("\n"))
    break

  case "EROFS":
    log.error("rofs", [er.message
              ,"This is most likely not a problem with npm itself"
              ,"and is related to the file system being read-only."
              ,"\nOften virtualized file systems, or other file systems"
              ,"that don't support symlinks, give this error."
              ].join("\n"))
    break

  default:
    log.error("", er.message || er)
    log.error("", ["", "If you need help, you may report this error at:"
                  ,"    <http://github.com/npm/npm/issues>"
                  ].join("\n"))
    break
  }

  exit(typeof er.errno === "number" ? er.errno : 1)
}

var writingLogFile = false
function writeLogFile (cb) {
  if (writingLogFile) return cb()
  writingLogFile = true
  wroteLogFile = true

  var fs = require("graceful-fs")
    , fstr = fs.createWriteStream("npm-debug.log")
    , util = require("util")
    , os = require("os")
    , out = ""

  log.record.forEach(function (m) {
    var pref = [m.id, m.level]
    if (m.prefix) pref.push(m.prefix)
    pref = pref.join(' ')

    m.message.trim().split(/\r?\n/).map(function (line) {
      return (pref + ' ' + line).trim()
    }).forEach(function (line) {
      out += line + os.EOL
    })
  })

  fstr.end(out)
  fstr.on("close", cb)
}
<commit_msg>consistently use double quotes<commit_after>
module.exports = errorHandler

var cbCalled = false
  , log = require("npmlog")
  , npm = require("../npm.js")
  , rm = require("rimraf")
  , itWorked = false
  , path = require("path")
  , wroteLogFile = false
  , exitCode = 0

process.on("exit", function (code) {
  // console.error("exit", code)
  if (!npm.config || !npm.config.loaded) return
  if (code) itWorked = false
  if (itWorked) log.info("ok")
  else {
    if (!cbCalled) {
      log.error("", "cb() never called!")
    }

    if (wroteLogFile) {
      // just a line break
      if (log.levels[log.level] <= log.levels.error) console.error("")

      log.error("",
                ["Please include the following file with any support request:"
                ,"    " + path.resolve("npm-debug.log")
                ].join("\n"))
      wroteLogFile = false
    }
    if (code) {
      log.error("code", code)
    }
  }

  var doExit = npm.config.get("_exit")
  if (doExit) {
    // actually exit.
    if (exitCode === 0 && !itWorked) {
      exitCode = 1
    }
    if (exitCode !== 0) process.exit(exitCode)
  } else {
    itWorked = false // ready for next exit
  }
})

function exit (code, noLog) {
  exitCode = exitCode || process.exitCode || code

  var doExit = npm.config ? npm.config.get("_exit") : true
  log.verbose("exit", [code, doExit])
  if (log.level === "silent") noLog = true

  if (code && !noLog) writeLogFile(reallyExit)
  else rm("npm-debug.log", function () { rm(npm.tmp, reallyExit) })

  function reallyExit() {
    // truncate once it's been written.
    log.record.length = 0

    itWorked = !code

    // just emit a fake exit event.
    // if we're really exiting, then let it exit on its own, so that
    // in-process stuff can finish or clean up first.
    if (!doExit) process.emit("exit", code)
    npm.spinner.stop()
  }
}

function errorHandler (er) {
  // console.error("errorHandler", er)
  if (!npm.config || !npm.config.loaded) {
    // logging won't work unless we pretend that it's ready
    er = er || new Error("Exit prior to config file resolving.")
    console.error(er.stack || er.message)
  }

  if (cbCalled) {
    er = er || new Error("Callback called more than once.")
  }

  cbCalled = true
  if (!er) return exit(0)
  if (typeof er === "string") {
    log.error("", er)
    return exit(1, true)
  } else if (!(er instanceof Error)) {
    log.error("weird error", er)
    return exit(1, true)
  }

  var m = er.code || er.message.match(/^(?:Error: )?(E[A-Z]+)/)
  if (m && !er.code) er.code = m

  ; [ "type"
    , "fstream_path"
    , "fstream_unc_path"
    , "fstream_type"
    , "fstream_class"
    , "fstream_finish_call"
    , "fstream_linkpath"
    , "stack"
    , "fstream_stack"
    , "statusCode"
    , "pkgid"
    ].forEach(function (k) {
      var v = er[k]
      if (!v) return
      if (k === "fstream_stack") v = v.join("\n")
      log.verbose(k, v)
    })

  log.verbose("cwd", process.cwd())

  var os = require("os")
  // log.error("System", os.type() + " " + os.release())
  // log.error("command", process.argv.map(JSON.stringify).join(" "))
  // log.error("node -v", process.version)
  // log.error("npm -v", npm.version)
  log.error("", os.type() + " " + os.release())
  log.error("argv", process.argv.map(JSON.stringify).join(" "))
  log.error("node", process.version)
  log.error("npm ", "v" + npm.version)

  ; [ "file"
    , "path"
    , "code"
    , "errno"
    , "syscall"
    ].forEach(function (k) {
      var v = er[k]
      if (v) log.error(k, v)
    })

  // just a line break
  if (log.levels[log.level] <= log.levels.error) console.error("")

  switch (er.code) {
  case "ECONNREFUSED":
    log.error("", er)
    log.error("", ["\nIf you are behind a proxy, please make sure that the"
              ,"'proxy' config is set properly.  See: 'npm help config'"
              ].join("\n"))
    break

  case "EACCES":
  case "EPERM":
    log.error("", er)
    log.error("", ["\nPlease try running this command again as root/Administrator."
              ].join("\n"))
    break

  case "ELIFECYCLE":
    log.error("", er.message)
    log.error("", ["","Failed at the "+er.pkgid+" "+er.stage+" script."
              ,"This is most likely a problem with the "+er.pkgname+" package,"
              ,"not with npm itself."
              ,"Tell the author that this fails on your system:"
              ,"    "+er.script
              ,"You can get their info via:"
              ,"    npm owner ls "+er.pkgname
              ,"There is likely additional logging output above."
              ].join("\n"))
    break

  case "ENOGIT":
    log.error("", er.message)
    log.error("", ["","Failed using git."
              ,"This is most likely not a problem with npm itself."
              ,"Please check if you have git installed and in your PATH."
              ].join("\n"))
    break

  case "EJSONPARSE":
    log.error("", er.message)
    log.error("", "File: "+er.file)
    log.error("", ["Failed to parse package.json data."
              ,"package.json must be actual JSON, not just JavaScript."
              ,"","This is not a bug in npm."
              ,"Tell the package author to fix their package.json file."
              ].join("\n"), "JSON.parse")
    break

  // TODO(isaacs)
  // Add a special case here for E401 and E403 explaining auth issues?

  case "E404":
    var msg = [er.message]
    if (er.pkgid && er.pkgid !== "-") {
      msg.push("", "'"+er.pkgid+"' is not in the npm registry."
              ,"You should bug the author to publish it (or use the name yourself!)")
      if (er.parent) {
        msg.push("It was specified as a dependency of '"+er.parent+"'")
      }
      msg.push("\nNote that you can also install from a"
              ,"tarball, folder, http url, or git url.")
    }
    // There's no need to have 404 in the message as well.
    msg[0] = msg[0].replace(/^404\s+/, "")
    log.error("404", msg.join("\n"))
    break

  case "EPUBLISHCONFLICT":
    log.error("publish fail", ["Cannot publish over existing version."
              ,"Update the 'version' field in package.json and try again."
              ,""
              ,"To automatically increment version numbers, see:"
              ,"    npm help version"
              ].join("\n"))
    break

  case "EISGIT":
    log.error("git", [er.message
              ,"    "+er.path
              ,"Refusing to remove it. Update manually,"
              ,"or move it out of the way first."
              ].join("\n"))
    break

  case "ECYCLE":
    log.error("cycle", [er.message
              ,"While installing: "+er.pkgid
              ,"Found a pathological dependency case that npm cannot solve."
              ,"Please report this to the package author."
              ].join("\n"))
    break

  case "EBADPLATFORM":
    log.error("notsup", [er.message
              ,"Not compatible with your operating system or architecture: "+er.pkgid
              ,"Valid OS:    "+er.os.join(",")
              ,"Valid Arch:  "+er.cpu.join(",")
              ,"Actual OS:   "+process.platform
              ,"Actual Arch: "+process.arch
              ].join("\n"))
    break

  case "EEXIST":
    log.error([er.message
              ,"File exists: "+er.path
              ,"Move it away, and try again."].join("\n"))
    break

  case "ENEEDAUTH":
    log.error("need auth", [er.message
              ,"You need to authorize this machine using `npm adduser`"
              ].join("\n"))
    break

  case "EPEERINVALID":
    var peerErrors = Object.keys(er.peersDepending).map(function (peer) {
      return "Peer " + peer + " wants " + er.packageName + "@"
        + er.peersDepending[peer]
    })
    log.error("peerinvalid", [er.message].concat(peerErrors).join("\n"))
    break

  case "ECONNRESET":
  case "ENOTFOUND":
  case "ETIMEDOUT":
    log.error("network", [er.message
              ,"This is most likely not a problem with npm itself"
              ,"and is related to network connectivity."
              ,"In most cases you are behind a proxy or have bad network settings."
              ,"\nIf you are behind a proxy, please make sure that the"
              ,"'proxy' config is set properly.  See: 'npm help config'"
              ].join("\n"))
    break

  case "ENOPACKAGEJSON":
    log.error("package.json", [er.message
              ,"This is most likely not a problem with npm itself."
              ,"npm can't find a package.json file in your current directory."
              ].join("\n"))
    break

  case "ETARGET":
    log.error("notarget", [er.message
              ,"This is most likely not a problem with npm itself."
              ,"In most cases you or one of your dependencies are requesting"
              ,"a package version that doesn't exist."
              ].join("\n"))
    break

  case "ENOTSUP":
    if (er.required) {
      log.error("notsup", [er.message
                ,"Not compatible with your version of node/npm: "+er.pkgid
                ,"Required: "+JSON.stringify(er.required)
                ,"Actual:   "
                +JSON.stringify({npm:npm.version
                                ,node:npm.config.get("node-version")})
                ].join("\n"))
      break
    } // else passthrough

  case "ENOSPC":
    log.error("nospc", [er.message
              ,"This is most likely not a problem with npm itself"
              ,"and is related to insufficient space on your system."
              ].join("\n"))
    break

  case "EROFS":
    log.error("rofs", [er.message
              ,"This is most likely not a problem with npm itself"
              ,"and is related to the file system being read-only."
              ,"\nOften virtualized file systems, or other file systems"
              ,"that don't support symlinks, give this error."
              ].join("\n"))
    break

  default:
    log.error("", er.message || er)
    log.error("", ["", "If you need help, you may report this error at:"
                  ,"    <http://github.com/npm/npm/issues>"
                  ].join("\n"))
    break
  }

  exit(typeof er.errno === "number" ? er.errno : 1)
}

var writingLogFile = false
function writeLogFile (cb) {
  if (writingLogFile) return cb()
  writingLogFile = true
  wroteLogFile = true

  var fs = require("graceful-fs")
    , fstr = fs.createWriteStream("npm-debug.log")
    , util = require("util")
    , os = require("os")
    , out = ""

  log.record.forEach(function (m) {
    var pref = [m.id, m.level]
    if (m.prefix) pref.push(m.prefix)
    pref = pref.join(" ")

    m.message.trim().split(/\r?\n/).map(function (line) {
      return (pref + " " + line).trim()
    }).forEach(function (line) {
      out += line + os.EOL
    })
  })

  fstr.end(out)
  fstr.on("close", cb)
}
<|endoftext|>


<commit_before>'use strict'
var npm = require('../npm.js')
var util = require('util')
var nameValidator = require('validate-npm-package-name')

module.exports = errorMessage

function errorMessage (er) {
  var short = []
  var detail = []
  if (er.optional) {
    short.push(['optional', 'Skipping failed optional dependency ' + er.optional + ':'])
  }
  switch (er.code) {
    case 'ECONNREFUSED':
      short.push(['', er])
      detail.push([
        '',
        [
          '\nIf you are behind a proxy, please make sure that the',
          "'proxy' config is set properly.  See: 'npm help config'"
        ].join('\n')
      ])
      break

    case 'EACCES':
    case 'EPERM':
      short.push(['', er])
      detail.push(['', ['\nPlease try running this command again as root/Administrator.'
                ].join('\n')])
      break

    case 'ELIFECYCLE':
      short.push(['', er.message])
      detail.push([
        '',
        [
          '',
          'Failed at the ' + er.pkgid + ' ' + er.stage + " script '" + er.script + "'.",
          'Make sure you have the latest version of node.js and npm installed.',
          'If you do, this is most likely a problem with the ' + er.pkgname + ' package,',
          'not with npm itself.',
          'Tell the author that this fails on your system:',
          '    ' + er.script,
          'You can get information on how to open an issue for this project with:',
          '    npm bugs ' + er.pkgname,
          'Or if that isn\'t available, you can get their info via:',
          '    npm owner ls ' + er.pkgname,
          'There is likely additional logging output above.'
        ].join('\n')]
      )
      break

    case 'ENOGIT':
      short.push(['', er.message])
      detail.push([
        '',
        [
          '',
          'Failed using git.',
          'This is most likely not a problem with npm itself.',
          'Please check if you have git installed and in your PATH.'
        ].join('\n')
      ])
      break

    case 'EJSONPARSE':
      short.push(['', er.message])
      short.push(['', 'File: ' + er.file])
      detail.push([
        '',
        [
          'Failed to parse package.json data.',
          'package.json must be actual JSON, not just JavaScript.',
          '',
          'This is not a bug in npm.',
          'Tell the package author to fix their package.json file.'
        ].join('\n'),
        'JSON.parse'
      ])
      break

    // TODO(isaacs)
    // Add a special case here for E401 and E403 explaining auth issues?

    case 'E404':
      // There's no need to have 404 in the message as well.
      var msg = er.message.replace(/^404\s+/, '')
      short.push(['404', msg])
      if (er.pkgid && er.pkgid !== '-') {
        detail.push(['404', ''])
        detail.push(['404', '', "'" + er.pkgid + "' is not in the npm registry."])

        var valResult = nameValidator(er.pkgid)

        if (valResult.validForNewPackages) {
          detail.push(['404', 'You should bug the author to publish it (or use the name yourself!)'])
        } else {
          detail.push(['404', 'Your package name is not valid, because', ''])

          var errorsArray = (valResult.errors || []).concat(valResult.warnings || [])
          errorsArray.forEach(function (item, idx) {
            detail.push(['404', ' ' + (idx + 1) + '. ' + item])
          })
        }

        if (er.parent) {
          detail.push(['404', "It was specified as a dependency of '" + er.parent + "'"])
        }
        detail.push(['404', '\nNote that you can also install from a'])
        detail.push(['404', 'tarball, folder, http url, or git url.'])
      }
      break

    case 'EPUBLISHCONFLICT':
      short.push(['publish fail', 'Cannot publish over existing version.'])
      detail.push(['publish fail', "Update the 'version' field in package.json and try again."])
      detail.push(['publish fail', ''])
      detail.push(['publish fail', 'To automatically increment version numbers, see:'])
      detail.push(['publish fail', '    npm help version'])
      break

    case 'EISGIT':
      short.push(['git', er.message])
      short.push(['git', '    ' + er.path])
      detail.push([
        'git',
        [
          'Refusing to remove it. Update manually,',
          'or move it out of the way first.'
        ].join('\n')
      ])
      break

    case 'ECYCLE':
      short.push([
        'cycle',
        [
          er.message,
          'While installing: ' + er.pkgid
        ].join('\n')
      ])
      detail.push([
        'cycle',
        [
          'Found a pathological dependency case that npm cannot solve.',
          'Please report this to the package author.'
        ].join('\n')
      ])
      break

    case 'EBADPLATFORM':
      short.push([
        'notsup',
        [
          'Not compatible with your operating system or architecture: ' + er.pkgid
        ].join('\n')
      ])
      detail.push([
        'notsup',
        [
          'Valid OS:    ' + (er.os.join ? er.os.join(',') : util.inspect(er.os)),
          'Valid Arch:  ' + (er.cpu.join ? er.cpu.join(',') : util.inspect(er.cpu)),
          'Actual OS:   ' + process.platform,
          'Actual Arch: ' + process.arch
        ].join('\n')
      ])
      break

    case 'EEXIST':
      short.push(['', er.message])
      short.push(['', 'File exists: ' + er.path])
      detail.push(['', 'Move it away, and try again.'])
      break

    case 'ENEEDAUTH':
      short.push(['need auth', er.message])
      detail.push(['need auth', 'You need to authorize this machine using `npm adduser`'])
      break

    case 'ECONNRESET':
    case 'ENOTFOUND':
    case 'ETIMEDOUT':
    case 'EAI_FAIL':
      short.push(['network', er.message])
      detail.push([
        'network',
        [
          'This is most likely not a problem with npm itself',
          'and is related to network connectivity.',
          'In most cases you are behind a proxy or have bad network settings.',
          '\nIf you are behind a proxy, please make sure that the',
          "'proxy' config is set properly.  See: 'npm help config'"
        ].join('\n')
      ])
      break

    case 'ENOPACKAGEJSON':
      short.push(['package.json', er.message])
      detail.push([
        'package.json',
        [
          'This is most likely not a problem with npm itself.',
          "npm can't find a package.json file in your current directory."
        ].join('\n')
      ])
      break

    case 'ETARGET':
      short.push(['notarget', er.message])
      msg = [
        'This is most likely not a problem with npm itself.',
        'In most cases you or one of your dependencies are requesting',
        "a package version that doesn't exist."
      ]
      if (er.parent) {
        msg.push("\nIt was specified as a dependency of '" + er.parent + "'\n")
      }
      detail.push(['notarget', msg.join('\n')])
      break

    case 'ENOTSUP':
      if (er.required) {
        short.push(['notsup', er.message])
        short.push(['notsup', 'Not compatible with your version of node/npm: ' + er.pkgid])
        detail.push([
          'notsup',
          [
            'Not compatible with your version of node/npm: ' + er.pkgid,
            'Required: ' + JSON.stringify(er.required),
            'Actual:   ' + JSON.stringify({
              npm: npm.version,
              node: npm.config.get('node-version')
            })
          ].join('\n')
        ])
        break
      } // else passthrough
      /*eslint no-fallthrough:0*/

    case 'ENOSPC':
      short.push(['nospc', er.message])
      detail.push([
        'nospc',
        [
          'This is most likely not a problem with npm itself',
          'and is related to insufficient space on your system.'
        ].join('\n')
      ])
      break

    case 'EROFS':
      short.push(['rofs', er.message])
      detail.push([
        'rofs',
        [
          'This is most likely not a problem with npm itself',
          'and is related to the file system being read-only.',
          '\nOften virtualized file systems, or other file systems',
          "that don't support symlinks, give this error."
        ].join('\n')
      ])
      break

    case 'ENOENT':
      short.push(['enoent', er.message])
      detail.push([
        'enoent',
        [
          er.message,
          'This is most likely not a problem with npm itself',
          'and is related to npm not being able to find a file.',
          er.file ? "\nCheck if the file '" + er.file + "' is present." : ''
        ].join('\n')
      ])
      break

    case 'EMISSINGARG':
    case 'EUNKNOWNTYPE':
    case 'EINVALIDTYPE':
    case 'ETOOMANYARGS':
      short.push(['typeerror', er.stack])
      detail.push([
        'typeerror',
        [
          'This is an error with npm itself. Please report this error at:',
          '    <https://github.com/npm/npm/issues>'
        ].join('\n')
      ])
      break

    case 'EISDIR':
      short.push(['eisdir', er.message])
      detail.push([
        'eisdir',
        [
          'This is most likely not a problem with npm itself',
          'and is related to npm not being able to find a package.json in',
          'a package you are trying to install.'
        ].join('\n')
      ])
      break

    default:
      short.push(['', er.message || er])
      detail.push([
        '',
        [
          '',
          'If you need help, you may report this error at:',
          '    <https://github.com/npm/npm/issues>'
        ].join('\n')
      ])
      break
  }
  return {summary: short, detail: detail}
}
<commit_msg>error-message: Improve error message for unsupported platforms<commit_after>'use strict'
var npm = require('../npm.js')
var util = require('util')
var nameValidator = require('validate-npm-package-name')

module.exports = errorMessage

function errorMessage (er) {
  var short = []
  var detail = []
  if (er.optional) {
    short.push(['optional', 'Skipping failed optional dependency ' + er.optional + ':'])
  }
  switch (er.code) {
    case 'ECONNREFUSED':
      short.push(['', er])
      detail.push([
        '',
        [
          '\nIf you are behind a proxy, please make sure that the',
          "'proxy' config is set properly.  See: 'npm help config'"
        ].join('\n')
      ])
      break

    case 'EACCES':
    case 'EPERM':
      short.push(['', er])
      detail.push(['', ['\nPlease try running this command again as root/Administrator.'
                ].join('\n')])
      break

    case 'ELIFECYCLE':
      short.push(['', er.message])
      detail.push([
        '',
        [
          '',
          'Failed at the ' + er.pkgid + ' ' + er.stage + " script '" + er.script + "'.",
          'Make sure you have the latest version of node.js and npm installed.',
          'If you do, this is most likely a problem with the ' + er.pkgname + ' package,',
          'not with npm itself.',
          'Tell the author that this fails on your system:',
          '    ' + er.script,
          'You can get information on how to open an issue for this project with:',
          '    npm bugs ' + er.pkgname,
          'Or if that isn\'t available, you can get their info via:',
          '    npm owner ls ' + er.pkgname,
          'There is likely additional logging output above.'
        ].join('\n')]
      )
      break

    case 'ENOGIT':
      short.push(['', er.message])
      detail.push([
        '',
        [
          '',
          'Failed using git.',
          'This is most likely not a problem with npm itself.',
          'Please check if you have git installed and in your PATH.'
        ].join('\n')
      ])
      break

    case 'EJSONPARSE':
      short.push(['', er.message])
      short.push(['', 'File: ' + er.file])
      detail.push([
        '',
        [
          'Failed to parse package.json data.',
          'package.json must be actual JSON, not just JavaScript.',
          '',
          'This is not a bug in npm.',
          'Tell the package author to fix their package.json file.'
        ].join('\n'),
        'JSON.parse'
      ])
      break

    // TODO(isaacs)
    // Add a special case here for E401 and E403 explaining auth issues?

    case 'E404':
      // There's no need to have 404 in the message as well.
      var msg = er.message.replace(/^404\s+/, '')
      short.push(['404', msg])
      if (er.pkgid && er.pkgid !== '-') {
        detail.push(['404', ''])
        detail.push(['404', '', "'" + er.pkgid + "' is not in the npm registry."])

        var valResult = nameValidator(er.pkgid)

        if (valResult.validForNewPackages) {
          detail.push(['404', 'You should bug the author to publish it (or use the name yourself!)'])
        } else {
          detail.push(['404', 'Your package name is not valid, because', ''])

          var errorsArray = (valResult.errors || []).concat(valResult.warnings || [])
          errorsArray.forEach(function (item, idx) {
            detail.push(['404', ' ' + (idx + 1) + '. ' + item])
          })
        }

        if (er.parent) {
          detail.push(['404', "It was specified as a dependency of '" + er.parent + "'"])
        }
        detail.push(['404', '\nNote that you can also install from a'])
        detail.push(['404', 'tarball, folder, http url, or git url.'])
      }
      break

    case 'EPUBLISHCONFLICT':
      short.push(['publish fail', 'Cannot publish over existing version.'])
      detail.push(['publish fail', "Update the 'version' field in package.json and try again."])
      detail.push(['publish fail', ''])
      detail.push(['publish fail', 'To automatically increment version numbers, see:'])
      detail.push(['publish fail', '    npm help version'])
      break

    case 'EISGIT':
      short.push(['git', er.message])
      short.push(['git', '    ' + er.path])
      detail.push([
        'git',
        [
          'Refusing to remove it. Update manually,',
          'or move it out of the way first.'
        ].join('\n')
      ])
      break

    case 'ECYCLE':
      short.push([
        'cycle',
        [
          er.message,
          'While installing: ' + er.pkgid
        ].join('\n')
      ])
      detail.push([
        'cycle',
        [
          'Found a pathological dependency case that npm cannot solve.',
          'Please report this to the package author.'
        ].join('\n')
      ])
      break

    case 'EBADPLATFORM':
      var validOs = er.os.join ? er.os.join(',') : er.os
      var validArch = er.cpu.join ? er.cpu.join(',') : er.cpu
      var expected = {os: validOs, arch: validArch}
      var actual = {os: process.platform, arch: process.arch}
      short.push([
        'notsup',
        [
          util.format('Unsupported platform for %s: wanted %j (current: %j)', er.pkgid, expected, actual)
        ].join('\n')
      ])
      detail.push([
        'notsup',
        [
          'Valid OS:    ' + validOs,
          'Valid Arch:  ' + validArch,
          'Actual OS:   ' + process.platform,
          'Actual Arch: ' + process.arch
        ].join('\n')
      ])
      break

    case 'EEXIST':
      short.push(['', er.message])
      short.push(['', 'File exists: ' + er.path])
      detail.push(['', 'Move it away, and try again.'])
      break

    case 'ENEEDAUTH':
      short.push(['need auth', er.message])
      detail.push(['need auth', 'You need to authorize this machine using `npm adduser`'])
      break

    case 'ECONNRESET':
    case 'ENOTFOUND':
    case 'ETIMEDOUT':
    case 'EAI_FAIL':
      short.push(['network', er.message])
      detail.push([
        'network',
        [
          'This is most likely not a problem with npm itself',
          'and is related to network connectivity.',
          'In most cases you are behind a proxy or have bad network settings.',
          '\nIf you are behind a proxy, please make sure that the',
          "'proxy' config is set properly.  See: 'npm help config'"
        ].join('\n')
      ])
      break

    case 'ENOPACKAGEJSON':
      short.push(['package.json', er.message])
      detail.push([
        'package.json',
        [
          'This is most likely not a problem with npm itself.',
          "npm can't find a package.json file in your current directory."
        ].join('\n')
      ])
      break

    case 'ETARGET':
      short.push(['notarget', er.message])
      msg = [
        'This is most likely not a problem with npm itself.',
        'In most cases you or one of your dependencies are requesting',
        "a package version that doesn't exist."
      ]
      if (er.parent) {
        msg.push("\nIt was specified as a dependency of '" + er.parent + "'\n")
      }
      detail.push(['notarget', msg.join('\n')])
      break

    case 'ENOTSUP':
      if (er.required) {
        short.push(['notsup', er.message])
        short.push(['notsup', 'Not compatible with your version of node/npm: ' + er.pkgid])
        detail.push([
          'notsup',
          [
            'Not compatible with your version of node/npm: ' + er.pkgid,
            'Required: ' + JSON.stringify(er.required),
            'Actual:   ' + JSON.stringify({
              npm: npm.version,
              node: npm.config.get('node-version')
            })
          ].join('\n')
        ])
        break
      } // else passthrough
      /*eslint no-fallthrough:0*/

    case 'ENOSPC':
      short.push(['nospc', er.message])
      detail.push([
        'nospc',
        [
          'This is most likely not a problem with npm itself',
          'and is related to insufficient space on your system.'
        ].join('\n')
      ])
      break

    case 'EROFS':
      short.push(['rofs', er.message])
      detail.push([
        'rofs',
        [
          'This is most likely not a problem with npm itself',
          'and is related to the file system being read-only.',
          '\nOften virtualized file systems, or other file systems',
          "that don't support symlinks, give this error."
        ].join('\n')
      ])
      break

    case 'ENOENT':
      short.push(['enoent', er.message])
      detail.push([
        'enoent',
        [
          er.message,
          'This is most likely not a problem with npm itself',
          'and is related to npm not being able to find a file.',
          er.file ? "\nCheck if the file '" + er.file + "' is present." : ''
        ].join('\n')
      ])
      break

    case 'EMISSINGARG':
    case 'EUNKNOWNTYPE':
    case 'EINVALIDTYPE':
    case 'ETOOMANYARGS':
      short.push(['typeerror', er.stack])
      detail.push([
        'typeerror',
        [
          'This is an error with npm itself. Please report this error at:',
          '    <https://github.com/npm/npm/issues>'
        ].join('\n')
      ])
      break

    case 'EISDIR':
      short.push(['eisdir', er.message])
      detail.push([
        'eisdir',
        [
          'This is most likely not a problem with npm itself',
          'and is related to npm not being able to find a package.json in',
          'a package you are trying to install.'
        ].join('\n')
      ])
      break

    default:
      short.push(['', er.message || er])
      detail.push([
        '',
        [
          '',
          'If you need help, you may report this error at:',
          '    <https://github.com/npm/npm/issues>'
        ].join('\n')
      ])
      break
  }
  return {summary: short, detail: detail}
}
<|endoftext|>


<commit_before>'use babel';

/** @jsx etch.dom */
/* @flow*/
import etch from 'etch';
import { Emitter, CompositeDisposable } from 'atom';
import type { TesterState } from '../types';

export default class ConsoleOutputView {
  properties: {
    state: TesterState;
    onclick: Function;
  }
  refs: any;
  element: any;
  panel: any;
  emitter: Emitter;
  disposables: CompositeDisposable;

  constructor(properties :{ state: TesterState, onclick: Function }) {
    this.properties = properties;
    this.emitter = new Emitter();
    this.disposables = new CompositeDisposable();

    etch.initialize(this);

    this.disposables.add(atom.tooltips.add(this.refs.failed, { title: 'Failed Tests' }));
    this.disposables.add(atom.tooltips.add(this.refs.skipped, { title: 'Skipped Tests' }));
    this.disposables.add(atom.tooltips.add(this.refs.passed, { title: 'Passed Tests' }));
    this.disposables.add(atom.tooltips.add(this.refs.beaker, { title: 'Click to toggle Tester' }));
  }

  render() {
    let messages = this.properties.state.messages;
    if (!messages || messages.constructor !== Array) {
      messages = [];
    }
    const failedTests = messages.filter(result => result.state === 'failed').length;
    const skippedTests = messages.filter(result => result.state === 'skipped').length;
    const passedTests = messages.filter(result => result.state === 'passed').length;
    return (

         0 ?
          'tester-bottom-status tester-status-failed highlight-error' :
          'tester-bottom-status tester-status-failed highlight') +
          (this.properties.state.testRunning ? ' tester-wait-bottom-status' : '')}>
          {failedTests}

         0 ?
          'tester-bottom-status tester-status-skipped highlight-warning' :
          'tester-bottom-status tester-status-skipped highlight') +
          (this.properties.state.testRunning ? ' tester-wait-bottom-status' : '')}>
          {skippedTests}

         0 ?
          'tester-bottom-status tester-status-passed highlight-success' :
          'tester-bottom-status tester-status-passed highlight') +
          (this.properties.state.testRunning ? ' tester-wait-bottom-status' : '')}>
          {passedTests}

    );
  }

  update(newState :TesterState) {
    if (this.properties.state !== newState) {
      this.properties.state = newState;
      return etch.update(this);
    }
    return Promise.resolve();
  }

  async destroy() {
    await etch.destroy(this);
    this.disposables.dispose();
  }

  getElement() {
    return this.element;
  }
}
<commit_msg>status bar animation for icon<commit_after>'use babel';

/** @jsx etch.dom */
/* @flow*/
import etch from 'etch';
import { Emitter, CompositeDisposable } from 'atom';
import type { TesterState } from '../types';

export default class ConsoleOutputView {
  properties: {
    state: TesterState;
    onclick: Function;
  }
  refs: any;
  element: any;
  panel: any;
  emitter: Emitter;
  disposables: CompositeDisposable;

  constructor(properties :{ state: TesterState, onclick: Function }) {
    this.properties = properties;
    this.emitter = new Emitter();
    this.disposables = new CompositeDisposable();

    etch.initialize(this);

    this.disposables.add(atom.tooltips.add(this.refs.failed, { title: 'Failed Tests' }));
    this.disposables.add(atom.tooltips.add(this.refs.skipped, { title: 'Skipped Tests' }));
    this.disposables.add(atom.tooltips.add(this.refs.passed, { title: 'Passed Tests' }));
    this.disposables.add(atom.tooltips.add(this.refs.beaker, { title: 'Click to toggle Tester' }));
  }

  render() {
    let messages = this.properties.state.messages;
    if (!messages || messages.constructor !== Array) {
      messages = [];
    }
    const failedTests = messages.filter(result => result.state === 'failed').length;
    const skippedTests = messages.filter(result => result.state === 'skipped').length;
    const passedTests = messages.filter(result => result.state === 'passed').length;
    return (

         0 ?
          'tester-bottom-status tester-status-failed highlight-error' :
          'tester-bottom-status tester-status-failed highlight') +
          (this.properties.state.testRunning ? ' tester-wait-bottom-status' : '')}>
          {failedTests}

         0 ?
          'tester-bottom-status tester-status-skipped highlight-warning' :
          'tester-bottom-status tester-status-skipped highlight') +
          (this.properties.state.testRunning ? ' tester-wait-bottom-status' : '')}>
          {skippedTests}

         0 ?
          'tester-bottom-status tester-status-passed highlight-success' :
          'tester-bottom-status tester-status-passed highlight') +
          (this.properties.state.testRunning ? ' tester-wait-bottom-status' : '')}>
          {passedTests}

    );
  }

  update(newState :TesterState) {
    if (this.properties.state !== newState) {
      this.properties.state = newState;
      return etch.update(this);
    }
    return Promise.resolve();
  }

  async destroy() {
    await etch.destroy(this);
    this.disposables.dispose();
  }

  getElement() {
    return this.element;
  }
}
<|endoftext|>


<commit_before>'use babel';
/**
  Stack Explorer Component
  @description Creates a tabbed side panel that displays information about
    the program's stacks, has the following tabs:
      - Stacktrace: show the stacktrace @ the current source line
      - Goroutines: show the running goroutines @ the current source line
      - Variables: shows the variables in the current scope
      - Breakpoints: view breakpoints and deactivate them

    Should be able to click on stack/goroutine frames and go to the source,
    and should be able to do the same for breakpoints
**/

import { CompositeDisposable } from 'atom';
import { BreakpointStore, DebuggerStateStore as StateStore } from '../stores';

export default class StackExplorerPanel {
  constructor() {
    this.disposables = new CompositeDisposable();
    this.element = null;
    this.$selectedTab = null;

    // Register Flux Stores
    this._stateStoreRm = StateStore
    .addListener(this.updateStack.bind(this)).remove;

    this._bpStoreRm = BreakpointStore
    .addListener(this.updateBreakpoints.bind(this)).remove;

    this.render();
  }

  render() {
    let $panelContainer = document.createElement('div');
    this._$panelContainer = $panelContainer;

    $panelContainer.classList.add('delve-stack-panel');
    $panelContainer.appendChild(this.buildTabBar());

    this.element = atom.workspace.addRightPanel({
      item: $panelContainer,
      priority: 200
    });
  }

  buildTabBar() {
    let $tabBar = document.createElement('ul');
    $tabBar.classList.add('tab-container');

    let $stackTab = document.createElement('li');
    $stackTab.classList.add('tab');
    $stackTab.classList.add('stacktrace-tab');
    $stackTab.innerHTML = '
Stacktrace
';
    $tabBar.appendChild($stackTab);

    let $grTab = document.createElement('li');
    $grTab.classList.add('tab');
    $grTab.classList.add('goroutine-tab');
    $grTab.innerHTML = '
Goroutines
';
    $tabBar.appendChild($grTab);

    let $varTab = document.createElement('li');
    $varTab.classList.add('tab');
    $varTab.classList.add('variables-tab');
    $varTab.innerHTML = '
Variables
';
    $tabBar.appendChild($varTab);

    let $bpTab = document.createElement('li');
    $bpTab.classList.add('tab');
    $bpTab.classList.add('breakpoints-tab');
    $bpTab.innerHTML = '
Breakpoints
';
    $tabBar.appendChild($bpTab);

    for (let i = 0; i < $tabBar.children.length; i++) {
      const $tab = $tabBar.children[i];
      $tab.addEventListener('click', () => {
        $tab.classList.add('active');
        if (this.$selectedTab) this.$selectedTab.classList.remove('active');
        this.$selectedTab = $tab;
      });
    }

    return $tabBar;
  }

  updateStack() {}
  updateBreakpoints() {}

  destroy() {
    this._stateStoreRm();
    this._bpStoreRm();

    if (this.element) this.element.destroy();
  }
}
<commit_msg>Set default stack explorer tab<commit_after>'use babel';
/**
  Stack Explorer Component
  @description Creates a tabbed side panel that displays information about
    the program's stacks, has the following tabs:
      - Stacktrace: show the stacktrace @ the current source line
      - Goroutines: show the running goroutines @ the current source line
      - Variables: shows the variables in the current scope
      - Breakpoints: view breakpoints and deactivate them

    Should be able to click on stack/goroutine frames and go to the source,
    and should be able to do the same for breakpoints
**/

import { CompositeDisposable } from 'atom';
import { BreakpointStore, DebuggerStateStore as StateStore } from '../stores';

export default class StackExplorerPanel {
  constructor() {
    this.disposables = new CompositeDisposable();
    this.element = null;
    this.$selectedTab = null;

    // Register Flux Stores
    this._stateStoreRm = StateStore
    .addListener(this.updateStack.bind(this)).remove;

    this._bpStoreRm = BreakpointStore
    .addListener(this.updateBreakpoints.bind(this)).remove;

    this.render();
  }

  render() {
    let $panelContainer = document.createElement('div');
    this._$panelContainer = $panelContainer;

    $panelContainer.classList.add('delve-stack-panel');
    $panelContainer.appendChild(this.buildTabBar());

    this.element = atom.workspace.addRightPanel({
      item: $panelContainer,
      priority: 200
    });
  }

  buildTabBar() {
    let $tabBar = document.createElement('ul');
    $tabBar.classList.add('tab-container');

    let $stackTab = document.createElement('li');
    $stackTab.classList.add('tab');
    $stackTab.classList.add('stacktrace-tab');
    $stackTab.innerHTML = '
Stacktrace
';
    $tabBar.appendChild($stackTab);

    let $grTab = document.createElement('li');
    $grTab.classList.add('tab');
    $grTab.classList.add('goroutine-tab');
    $grTab.innerHTML = '
Goroutines
';
    $tabBar.appendChild($grTab);

    let $varTab = document.createElement('li');
    $varTab.classList.add('tab');
    $varTab.classList.add('variables-tab');
    $varTab.innerHTML = '
Variables
';
    $tabBar.appendChild($varTab);

    let $bpTab = document.createElement('li');
    $bpTab.classList.add('tab');
    $bpTab.classList.add('breakpoints-tab');
    $bpTab.innerHTML = '
Breakpoints
';
    $tabBar.appendChild($bpTab);

    // Default active is stacktrace
    $stackTab.classList.add('active');
    this.$selectedTab = $stackTab;

    for (let i = 0; i < $tabBar.children.length; i++) {
      const $tab = $tabBar.children[i];
      $tab.addEventListener('click', () => {
        $tab.classList.add('active');
        if (this.$selectedTab) this.$selectedTab.classList.remove('active');
        this.$selectedTab = $tab;
      });
    }

    return $tabBar;
  }

  updateStack() {}
  updateBreakpoints() {}

  destroy() {
    this._stateStoreRm();
    this._bpStoreRm();

    if (this.element) this.element.destroy();
  }
}
<|endoftext|>


<commit_before>import emitter from 'mitt';
import audioPool from './utils/audio-pool';
import feature from './utils/feature';
import { sleep } from './utils/async';
import settings from './settings';
import pageVisibility from './utils/page-visibility';

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

let context;
let source;
let gainNode;
let loopCount;
let duration = 0;
let lastTime = 0;
let audioTime;
let lastLoopProgress = 0;
let startTime;
let contextStartTime;
let audioElement;
let request;
let onCanPlayThrough;
let onPause;
let onPlay;
let onSeeking;
let pauseTime;
let muted = false;
let pauseCount = 0;

const FADE_OUT_SECONDS = 2;
const ALMOST_ZERO = 1e-4;

let scheduledTime;
const audio = Object.assign(emitter(), {
  tick(staticTime) {
    if (!context || !duration) return;

    // Because there is no reliable way to see if an audio element is paused,
    // we need to see if its currentTime property changed. Because the currentTime
    // doesn't always change each frame, we wait for it to not have changed
    // 2 times, before actually pausing:
    if (audioElement) {
      if (audioTime === audioElement.currentTime) {
        pauseCount++;
      } else {
        pauseCount = 0;
      }
      if (pauseCount > 1) return;
    }
    const isStatic = staticTime !== undefined;
    this.time = (isStatic
      ? staticTime
      : (pauseTime || (Date.now() - startTime)) / 1000
    ) % duration;

    if (!isStatic) {
      // The time as reported by the context or audio element:
      audioTime = (audioElement
        ? audioElement.currentTime
        : context.currentTime - contextStartTime) % audio.duration;

      // If our time is running more than 5ms out of sync, correct it:
      if (Math.abs(this.time - audioTime) > 0.05) {
        this.time = audioTime;
        startTime = Date.now() - this.time * 1000;
      }
    }
    const { loopDuration } = settings;
    const time = this.time;
    // The position within the track as a multiple of loopDuration:
    this.progress = time > 0
      ? time / loopDuration
      : 0;
    // The position within the individual loop as a value between 0 - 1:
    this.loopProgress = (time % loopDuration) / loopDuration;

    // True when the audio looped, false otherwise:
    this.looped = (time < lastTime) && Math.abs(time - lastTime) > (audio.duration * 0.9);
    if (this.looped) {
      // The index of the loop, used when the audio has more than one loops:
      this.loopIndex = Math.floor(this.progress * loopCount);
      this.loopCount++;
    }

    this.totalProgress = this.loopCount * loopCount + this.progress;
    this.totalTime = this.totalProgress * loopDuration;
    lastTime = time;
    if (this.totalProgress - lastLoopProgress > 1) {
      lastLoopProgress = Math.floor(this.totalProgress);
      this.emit('loop', lastLoopProgress);
    }
  },

  load(param) {
    return new Promise(async (resolve, reject) => {
      audio.reset();
      context = new AudioContext();
      gainNode = context.createGain();
      // Reset time, set loop count
      lastTime = 0;
      lastLoopProgress = 0;
      loopCount = param.loops === undefined
        ? 1
        : param.loops;
      this.loopCount = 0;
      const canPlay = () => {
        this.duration = duration;
        resolve(param.src);
      };

      if (param.loopOffset) {
        this.loopOffset = param.loopOffset;
      }

      if (param.progressive) {
        audioElement = feature.isMobile
          ? audioPool.get()
          : new Audio();
        audioElement.addEventListener('ended', () => audio.emit('ended'));
        audioElement.autoplay = true;
        audioElement.src = param.src;
        audioElement.loop = param.loop === undefined ? true : param.loop;
        const getAudioTime = () => audioElement.currentTime * 1000;
        onCanPlayThrough = () => {
          duration = audioElement.duration;
          canPlay();
          audioElement.removeEventListener('canplaythrough', onCanPlayThrough);
        };
        onPause = () => {
          this.paused = true;
          pauseTime = getAudioTime();
          this.emit('pause');
        };
        onPlay = () => {
          this.paused = false;
          pauseTime = null;
          this.emit('play');
        };
        onSeeking = () => {
          startTime = Date.now() - getAudioTime();
          if (pauseTime) {
            pauseTime = getAudioTime();
          }
          this.time = audioElement.currentTime;
        };
        audioElement.addEventListener('canplaythrough', onCanPlayThrough);
        audioElement.addEventListener('pause', onPause);
        audioElement.addEventListener('playing', onPlay);
        audioElement.addEventListener('seeking', onSeeking);
        source = context.createMediaElementSource(audioElement);
      } else {
        source = context.createBufferSource();
        request = new XMLHttpRequest();
        request.open('GET', param.src, true);
        request.responseType = 'arraybuffer';
        request.onload = () => {
          context.decodeAudioData(
            request.response,
            (response) => {
              // Load the file into the buffer
              source.buffer = response;
              duration = source.buffer.duration;
              source.loop = param.loop === undefined ? true : param.loop;
              source.start(0);
              contextStartTime = context.currentTime;
              startTime = Date.now();
              canPlay();
            },
            reject
          );
        };
        request.send();
      }
      source.connect(gainNode);
      gainNode.connect(context.destination);
      if (muted) this.mute();
    });
  },

  play() {
    this.paused = false;
    if (context) context.resume();
    if (audioElement) {
      audioElement.play();
    }
    if (!this.muted) {
      audio.fadeIn();
    }
  },

  pause() {
    this.paused = true;
    if (context) context.suspend();
    if (audioElement) {
      audioElement.pause();
    }
  },

  toggle() {
    this[this.paused ? 'play' : 'pause']();
  },

  gotoTime(time) {
    audioElement.currentTime = time;
    this.tick();
  },

  previousLoop() {
    const time = (Math.round(this.progress) - 1.1) * settings.loopDuration;
    this.gotoTime(Math.max(0, Math.min(this.duration, time)));
  },

  nextLoop() {
    const time = (Math.round(this.progress) + 0.9) * settings.loopDuration;
    this.gotoTime(Math.max(0, Math.min(this.duration, time)));
  },

  resetValues() {
    this.progress = 0;
    this.time = 0;
    this.totalTime = 0;
    this.loopProgress = 0;
    this.totalProgress = 0;
    this.looped = false;
    duration = 0;
    lastTime = null;
  },

  reset() {
    if (context) {
      context.close();
    }
    audio.resetValues();
    // Cancel loading of audioElement:
    if (audioElement) {
      audioElement.removeEventListener('canplaythrough', onCanPlayThrough);
      audioElement.removeEventListener('pause', onPause);
      audioElement.removeEventListener('playing', onPlay);
      audioElement.removeEventListener('seeking', onSeeking);
      audioElement.pause();
      audioElement = null;
      onCanPlayThrough = null;
    }
    if (request) {
      request.abort();
      request.onload = null;
      request = null;
    }
    pauseTime = contextStartTime = null;
    startTime = 0;
  },

  rewind() {
    if (audioElement) {
      audioElement.currentTime = 0;
      gainNode.gain.value = muted ? 0.001 : 1;
    }
  },

  mute() {
    if (scheduledTime) {
      gainNode.gain.cancelScheduledValues(scheduledTime);
    }
    gainNode.gain.value = 0.001;
    if (audioElement) {
      audioElement.muted = true;
    }
  },

  unmute() {
    if (scheduledTime) {
      gainNode.gain.cancelScheduledValues(scheduledTime);
    }
    gainNode.gain.value = 1;
    if (audioElement) {
      audioElement.muted = false;
    }
  },

  isMuted() {
    return muted;
  },

  toggleMute() {
    this[muted ? 'unmute' : 'mute']();
    muted = !muted;
    return muted;
  },

  async fadeOut(fadeDuration = FADE_OUT_SECONDS) {
    if (!context) return;
    if (scheduledTime) {
      gainNode.gain.cancelScheduledValues(scheduledTime);
    }
    scheduledTime = context.currentTime;
    gainNode.gain.exponentialRampToValueAtTime(
      ALMOST_ZERO,
      scheduledTime + fadeDuration
    );
    return sleep(fadeDuration * 1000);
  },

  async fadeIn(fadeDuration = FADE_OUT_SECONDS) {
    if (!context || muted) return;
    if (scheduledTime) {
      gainNode.gain.cancelScheduledValues(scheduledTime);
    }
    scheduledTime = context.currentTime;
    gainNode.gain.exponentialRampToValueAtTime(
      1,
      scheduledTime + fadeDuration
    );
    return sleep(fadeDuration * 1000);
  },

  time: 0,
  loopIndex: 0,
});

audio.resetValues();

pageVisibility.on('change', (visible) => {
  audio[visible ? 'play' : 'pause']();
});

export default audio;
<commit_msg>fix audio sync – closes #525<commit_after>import emitter from 'mitt';
import audioPool from './utils/audio-pool';
import feature from './utils/feature';
import { sleep } from './utils/async';
import settings from './settings';
import pageVisibility from './utils/page-visibility';

const logging = false;

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

let context;
let source;
let gainNode;
let loopCount;
let duration = 0;
let lastTime = 0;
let audioTime;
let lastLoopProgress = 0;
let startTime;
let contextStartTime;
let audioElement;
let request;
let onCanPlayThrough;
let onPause;
let onPlay;
let onSeeking;
let pauseTime;
let muted = false;

const FADE_OUT_SECONDS = 2;
const ALMOST_ZERO = 1e-4;

// The allowable sync difference on android is higher, because for some reason
// it is is much less accurate in reporting HTMLMediaElement.currentTime:
const ALLOWED_SYNC_DIFFERENCE = (feature.isMobile && !feature.isIOs) ? 0.1 : 0.05;

let scheduledTime;
const audio = Object.assign(emitter(), {
  tick(staticTime) {
    if (!context || !duration) return;

    // If we don't have enough data to play the audio,
    // pause playback by returning early:
    // https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState
    if (audioElement && audioElement.readyState === 2) return;

    const now = Date.now();

    const isStatic = staticTime !== undefined;
    this.time = (isStatic
      ? staticTime
      : (pauseTime || (now - startTime)) / 1000
    ) % duration;

    if (!isStatic) {
      // The time as reported by the context or audio element:
      audioTime = (audioElement
        ? audioElement.currentTime
        : context.currentTime - contextStartTime) % audio.duration;

      // If our animation time is running out of sync with the time reported
      // by the audio element correct it:
      const syncDiff = Math.abs(this.time - audioTime);
      if (syncDiff > ALLOWED_SYNC_DIFFERENCE) {
        if (logging) {
          console.log(`syncing animation to audio by ${Math.round(syncDiff * 1000)} ms`);
        }
        this.time = audioTime;
        startTime = now - audioTime * 1000;
      }
    }
    const { loopDuration } = settings;
    const time = this.time;
    // The position within the track as a multiple of loopDuration:
    this.progress = time > 0
      ? time / loopDuration
      : 0;
    // The position within the individual loop as a value between 0 - 1:
    this.loopProgress = (time % loopDuration) / loopDuration;

    // True when the audio looped, false otherwise:
    this.looped = (time < lastTime) && Math.abs(time - lastTime) > (audio.duration * 0.9);
    if (this.looped) {
      // The index of the loop, used when the audio has more than one loops:
      this.loopIndex = Math.floor(this.progress * loopCount);
      this.loopCount++;
    }

    this.totalProgress = this.loopCount * loopCount + this.progress;
    this.totalTime = this.totalProgress * loopDuration;
    lastTime = time;
    if (this.totalProgress - lastLoopProgress > 1) {
      lastLoopProgress = Math.floor(this.totalProgress);
      this.emit('loop', lastLoopProgress);
    }
  },

  load(param) {
    return new Promise(async (resolve, reject) => {
      audio.reset();
      context = new AudioContext();
      gainNode = context.createGain();
      // Reset time, set loop count
      lastTime = 0;
      lastLoopProgress = 0;
      loopCount = param.loops === undefined
        ? 1
        : param.loops;
      this.loopCount = 0;
      const canPlay = () => {
        this.duration = duration;
        resolve(param.src);
      };

      if (param.loopOffset) {
        this.loopOffset = param.loopOffset;
      }

      if (param.progressive) {
        audioElement = feature.isMobile
          ? audioPool.get()
          : new Audio();
        audioElement.addEventListener('ended', () => audio.emit('ended'));
        audioElement.autoplay = true;
        audioElement.src = param.src;
        audioElement.loop = param.loop === undefined ? true : param.loop;
        const getAudioTime = () => audioElement.currentTime * 1000;
        onCanPlayThrough = () => {
          duration = audioElement.duration;
          canPlay();
          audioElement.removeEventListener('canplaythrough', onCanPlayThrough);
        };
        onPause = () => {
          this.paused = true;
          pauseTime = getAudioTime();
          this.emit('pause');
        };
        onPlay = () => {
          this.paused = false;
          pauseTime = null;
          this.emit('play');
        };
        onSeeking = () => {
          startTime = Date.now() - getAudioTime();
          if (pauseTime) {
            pauseTime = getAudioTime();
          }
          this.time = audioElement.currentTime;
        };
        audioElement.addEventListener('canplaythrough', onCanPlayThrough);
        audioElement.addEventListener('pause', onPause);
        audioElement.addEventListener('playing', onPlay);
        audioElement.addEventListener('seeking', onSeeking);
        source = context.createMediaElementSource(audioElement);
      } else {
        source = context.createBufferSource();
        request = new XMLHttpRequest();
        request.open('GET', param.src, true);
        request.responseType = 'arraybuffer';
        request.onload = () => {
          context.decodeAudioData(
            request.response,
            (response) => {
              // Load the file into the buffer
              source.buffer = response;
              duration = source.buffer.duration;
              source.loop = param.loop === undefined ? true : param.loop;
              source.start(0);
              contextStartTime = context.currentTime;
              startTime = Date.now();
              canPlay();
            },
            reject
          );
        };
        request.send();
      }
      source.connect(gainNode);
      gainNode.connect(context.destination);
      if (muted) this.mute();
    });
  },

  play() {
    this.paused = false;
    if (context) context.resume();
    if (audioElement) {
      audioElement.play();
    }
    if (!this.muted) {
      audio.fadeIn();
    }
  },

  pause() {
    this.paused = true;
    if (context) context.suspend();
    if (audioElement) {
      audioElement.pause();
    }
  },

  toggle() {
    this[this.paused ? 'play' : 'pause']();
  },

  gotoTime(time) {
    audioElement.currentTime = time;
    this.tick();
  },

  previousLoop() {
    const time = (Math.round(this.progress) - 1.1) * settings.loopDuration;
    this.gotoTime(Math.max(0, Math.min(this.duration, time)));
  },

  nextLoop() {
    const time = (Math.round(this.progress) + 0.9) * settings.loopDuration;
    this.gotoTime(Math.max(0, Math.min(this.duration, time)));
  },

  resetValues() {
    this.progress = 0;
    this.time = 0;
    this.totalTime = 0;
    this.loopProgress = 0;
    this.totalProgress = 0;
    this.looped = false;
    duration = 0;
    lastTime = null;
  },

  reset() {
    if (context) {
      context.close();
    }
    audio.resetValues();
    // Cancel loading of audioElement:
    if (audioElement) {
      audioElement.removeEventListener('canplaythrough', onCanPlayThrough);
      audioElement.removeEventListener('pause', onPause);
      audioElement.removeEventListener('playing', onPlay);
      audioElement.removeEventListener('seeking', onSeeking);
      audioElement.pause();
      audioElement = null;
      onCanPlayThrough = null;
    }
    if (request) {
      request.abort();
      request.onload = null;
      request = null;
    }
    pauseTime = contextStartTime = null;
    startTime = 0;
  },

  rewind() {
    if (audioElement) {
      audioElement.currentTime = 0;
      gainNode.gain.value = muted ? 0.001 : 1;
    }
  },

  mute() {
    if (scheduledTime) {
      gainNode.gain.cancelScheduledValues(scheduledTime);
    }
    gainNode.gain.value = 0.001;
    if (audioElement) {
      audioElement.muted = true;
    }
  },

  unmute() {
    if (scheduledTime) {
      gainNode.gain.cancelScheduledValues(scheduledTime);
    }
    gainNode.gain.value = 1;
    if (audioElement) {
      audioElement.muted = false;
    }
  },

  isMuted() {
    return muted;
  },

  toggleMute() {
    this[muted ? 'unmute' : 'mute']();
    muted = !muted;
    return muted;
  },

  async fadeOut(fadeDuration = FADE_OUT_SECONDS) {
    if (!context) return;
    if (scheduledTime) {
      gainNode.gain.cancelScheduledValues(scheduledTime);
    }
    scheduledTime = context.currentTime;
    gainNode.gain.exponentialRampToValueAtTime(
      ALMOST_ZERO,
      scheduledTime + fadeDuration
    );
    return sleep(fadeDuration * 1000);
  },

  async fadeIn(fadeDuration = FADE_OUT_SECONDS) {
    if (!context || muted) return;
    if (scheduledTime) {
      gainNode.gain.cancelScheduledValues(scheduledTime);
    }
    scheduledTime = context.currentTime;
    gainNode.gain.exponentialRampToValueAtTime(
      1,
      scheduledTime + fadeDuration
    );
    return sleep(fadeDuration * 1000);
  },

  time: 0,
  loopIndex: 0,
});

audio.resetValues();

pageVisibility.on('change', (visible) => {
  audio[visible ? 'play' : 'pause']();
});

export default audio;
<|endoftext|>


<commit_before>// http://redux-form.com/7.0.1/docs/api/Field.md/
import dateLight from 'template-tools/src/utils/dateLight'

export const string = (opts = {}) => {
  return Object.assign({}, {

  }, opts)
}

export const money = (opts = {}) => {
  return Object.assign({}, {

  }, opts)
}

export const number = (opts = {}) => {
  return Object.assign({}, {
    normalize: (value) => {
      if(value.match(/\.$/)) return value
      // the case where it strips the last zero from an amount like 9.50
      if(value.match(/\.\d+0$/)) return value
      const num = parseFloat(value)
      return isNaN(num) ? value : num
      return value
    }
  }, opts)
}

export const date = (opts = {}) => {
  return Object.assign({}, {
    format: (value) => value ? new Date(value) : value,
    normalize: (value) => value ? dateLight.sqlDate(value, true) : null
  }, opts)
}

export const time = (opts = {}) => {
  return Object.assign({}, {

  }, opts)
}

export const raw = (opts = {}) => {
  return Object.assign({}, {

  }, opts)
}

const Models = {
  string,
  number,
  date,
  time,
  raw
}

export default Models<commit_msg>allow -0 in number fields<commit_after>// http://redux-form.com/7.0.1/docs/api/Field.md/
import dateLight from 'template-tools/src/utils/dateLight'

export const string = (opts = {}) => {
  return Object.assign({}, {

  }, opts)
}

export const money = (opts = {}) => {
  return Object.assign({}, {

  }, opts)
}

export const number = (opts = {}) => {
  return Object.assign({}, {
    normalize: (value) => {
      if(value.match(/\.$/)) return value
      // the case where it strips the last zero from an amount like 9.50
      if(value.match(/\.\d+0$/)) return value
      if(value.match(/^-0$/)) return value
      const num = parseFloat(value)
      return isNaN(num) ? value : num
      return value
    }
  }, opts)
}

export const date = (opts = {}) => {
  return Object.assign({}, {
    format: (value) => value ? new Date(value) : value,
    normalize: (value) => value ? dateLight.sqlDate(value, true) : null
  }, opts)
}

export const time = (opts = {}) => {
  return Object.assign({}, {

  }, opts)
}

export const raw = (opts = {}) => {
  return Object.assign({}, {

  }, opts)
}

const Models = {
  string,
  number,
  date,
  time,
  raw
}

export default Models<|endoftext|>


<commit_before>var WebPage = require('webpage');
var System = require('system');
address = System.args[1];
var index = 0;

var screenshots = [
  {"dimensions" : [975,500],
  "filename": './screenshots/screenshot_l.png'},
  {"dimensions" : [720,400],
  "filename": './screenshots/screenshot_m.png'},
  {"dimensions" : [400,200],
  "filename": './screenshots/screenshot_s.png'}
];

var capturescreen = function(dimensions, filename){
  var page = WebPage.create();
  page.viewportSize = {
    width: dimensions[0],
    height: dimensions[1]
  };
  page.open(address);
  page.onLoadFinished = setTimeout(function() {
      page.render(filename);
      page.close();
      index++;
      // Give it a second before calling next.
      // Phantom runs into some sort of race condition without this
      setTimeout(nextPage, 1000);
  }, 3000);
}

var nextPage = function(){
  if(!screenshots[index]){
    phantom.exit();
  }
  capturescreen(screenshots[index].dimensions, screenshots[index].filename);
}

nextPage();<commit_msg>Add height is not absoulte note<commit_after>var WebPage = require('webpage'),
    System = require('system'),
    address = System.args[1],
    index = 0;

// All the sizes to screenshot.
// Note: PhantomJs uses the heights specified here as a min-height criteria
var screenshots = [
  {"dimensions" : [970,300],
  "filename": './screenshots/screenshot_l.png'},
  {"dimensions" : [720,300],
  "filename": './screenshots/screenshot_m.png'},
  {"dimensions" : [400,200],
  "filename": './screenshots/screenshot_s.png'}
];

var capturescreen = function(dimensions, filename){
  var page = WebPage.create();
  page.viewportSize = {
    width: dimensions[0],
    height: dimensions[1]
  };
  page.open(address);
  page.onLoadFinished = setTimeout(function() {
      page.render(filename);
      page.close();
      index++;

      // Give it a second before calling next.
      // Phantom runs into some sort of race condition without this
      setTimeout(nextPage, 1000);
  }, 3000);
}

var nextPage = function(){
  if(!screenshots[index]){
    phantom.exit();
  }
  capturescreen(screenshots[index].dimensions, screenshots[index].filename);
}

nextPage();<|endoftext|>


<commit_before>var BigInteger = require('./jsbn/jsbn');
var sec = require('./jsbn/sec');
var base58 = require('./base58');
var util = require('./util');
var convert = require('./convert');
var Address = require('./address');
var ecdsa = require('./ecdsa');
var ECPointFp = require('./jsbn/ec').ECPointFp;
var Network = require('./network')

var ecparams = sec("secp256k1");

// input can be nothing, array of bytes, hex string, or base58 string
var ECKey = function (input, compressed) {
    if (!(this instanceof ECKey)) { return new ECKey(input, compressed); }
    if (!input) {
        // Generate new key
        var n = ecparams.getN();
        this.priv = ecdsa.getBigRandom(n);
        this.compressed = compressed || false;
    }
    else this.import(input,compressed)
};

ECKey.prototype.import = function (input,compressed) {
    function has(li,v) { return li.indexOf(v) >= 0 }
    function fromBin(x) { return BigInteger.fromByteArrayUnsigned(x) }
    this.priv =
          input instanceof ECKey                   ? input.priv
        : input instanceof BigInteger              ? input.mod(ecparams.getN())
        : Array.isArray(input)                      ? fromBin(input.slice(0,32))
        : typeof input != "string"                 ? null
        : input.length == 44                       ? fromBin(convert.base64ToBytes(input))
        : input.length == 51 && input[0] == '5'    ? fromBin(base58.checkDecode(input))
        : input.length == 51 && input[0] == '9'    ? fromBin(base58.checkDecode(input))
        : input.length == 52 && has('LK',input[0]) ? fromBin(base58.checkDecode(input).slice(0,32))
        : input.length == 52 && input[0] == 'c'    ? fromBin(base58.checkDecode(input).slice(0,32))
        : has([64,65],input.length)                ? fromBin(convert.hexToBytes(input.slice(0,64)))
                                                   : null

    this.compressed =
          compressed !== undefined                 ? compressed
        : input instanceof ECKey                   ? input.compressed
        : input instanceof BigInteger              ? false
        : Array.isArray(input)                      ? false
        : typeof input != "string"                 ? null
        : input.length == 44                       ? false
        : input.length == 51 && input[0] == '5'    ? false
        : input.length == 51 && input[0] == '9'    ? false
        : input.length == 52 && has('LK',input[0]) ? true
        : input.length == 52 && input[0] == 'c'    ? true
        : input.length == 64                       ? false
        : input.length == 65                       ? true
                                                   : null
};

ECKey.prototype.getPub = function(compressed) {
    if (compressed === undefined) compressed = this.compressed
    return ECPubKey(ecparams.getG().multiply(this.priv),compressed)
}

/**
 * @deprecated Reserved keyword, factory pattern. Use toHex, toBytes, etc.
 */
ECKey.prototype['export'] = function(format) {
    var format = format || 'hex'
    return this['to' + format.substr(0, 1).toUpperCase() + format.substr(1)]()
}

ECKey.prototype.toBin = function() {
    return convert.bytesToString(this.toBytes())
}

ECKey.version_bytes = {
  0: 128,
  111: 239
}

ECKey.prototype.toWif = function(version) {
    version = version || Network.mainnet.addressVersion;

    return base58.checkEncode(this.toBytes(), ECKey.version_bytes[version])
}

ECKey.prototype.toHex = function() {
    return convert.bytesToHex(this.toBytes())
}

ECKey.prototype.toBytes = function() {
    var bytes = this.priv.toByteArrayUnsigned();
    if (this.compressed) bytes.push(1)
    return bytes
}

ECKey.prototype.toBase64 = function() {
    return convert.bytesToBase64(this.toBytes())
}

ECKey.prototype.toString = ECKey.prototype.toHex

ECKey.prototype.getAddress = function(version) {
    return this.getPub().getAddress(version)
}

ECKey.prototype.add = function(key) {
    return ECKey(this.priv.add(ECKey(key).priv),this.compressed)
}

ECKey.prototype.multiply = function(key) {
    return ECKey(this.priv.multiply(ECKey(key).priv),this.compressed)
}

ECKey.prototype.sign = function(hash) {
  return ecdsa.sign(hash, this.priv);
}

ECKey.prototype.verify = function(hash, sig) {
  return this.getPub().verify(hash, sig)
}

var ECPubKey = function(input, compressed) {
    if (!(this instanceof ECPubKey)) { return new ECPubKey(input, compressed); }
    if (!input) {
        // Generate new key
        var n = ecparams.getN();
        this.pub = ecparams.getG().multiply(ecdsa.getBigRandom(n))
        this.compressed = compressed || false;
    }
    else this.import(input,compressed)
}

ECPubKey.prototype.import = function(input,compressed) {
    var decode = function(x) { return ECPointFp.decodeFrom(ecparams.getCurve(), x) }
    this.pub =
          input instanceof ECPointFp ? input
        : input instanceof ECKey     ? ecparams.getG().multiply(input.priv)
        : input instanceof ECPubKey  ? input.pub
        : typeof input == "string"   ? decode(convert.hexToBytes(input))
        : Array.isArray(input)        ? decode(input)
                                     : ecparams.getG().multiply(ecdsa.getBigRandom(ecparams.getN()))

    this.compressed =
          compressed                 ? compressed
        : input instanceof ECPointFp ? input.compressed
        : input instanceof ECPubKey  ? input.compressed
                                     : (this.pub[0] < 4)
}

ECPubKey.prototype.add = function(key) {
    return ECPubKey(this.pub.add(ECPubKey(key).pub),this.compressed)
}

ECPubKey.prototype.multiply = function(key) {
    return ECPubKey(this.pub.multiply(ECKey(key).priv),this.compressed)
}

ECPubKey.prototype['export'] = function(format) {
    var format = format || 'hex';
    return this['to' + format.substr(0, 1).toUpperCase() + format.substr(1)]()
}

ECPubKey.prototype.toBytes = function(compressed) {
    if (compressed === undefined) compressed = this.compressed
    return this.pub.getEncoded(compressed)
}

ECPubKey.prototype.toHex = function(compressed) {
    return convert.bytesToHex(this.toBytes(compressed))
}

ECPubKey.prototype.toBin = function(compressed) {
    return convert.bytesToString(this.toBytes(compressed))
}

ECPubKey.prototype.toWif = function(version) {
    version = version || Network.mainnet.addressVersion;

    return base58.checkEncode(this.toBytes(), version)
}

ECPubKey.prototype.toString = ECPubKey.prototype.toHex

ECPubKey.prototype.getAddress = function(version) {
    version = version || Network.mainnet.addressVersion;

    return new Address(util.sha256ripe160(this.toBytes()), version);
}

ECPubKey.prototype.verify = function(hash, sig) {
  return ecdsa.verify(hash, sig, this.toBytes())
}

module.exports = {
  ECKey: ECKey,
  ECPubKey: ECPubKey
}
<commit_msg>Removes dangerous private key throwaway<commit_after>var BigInteger = require('./jsbn/jsbn');
var sec = require('./jsbn/sec');
var base58 = require('./base58');
var util = require('./util');
var convert = require('./convert');
var Address = require('./address');
var ecdsa = require('./ecdsa');
var ECPointFp = require('./jsbn/ec').ECPointFp;
var Network = require('./network')

var ecparams = sec("secp256k1");

// input can be nothing, array of bytes, hex string, or base58 string
var ECKey = function (input, compressed) {
    if (!(this instanceof ECKey)) { return new ECKey(input, compressed); }
    if (!input) {
        // Generate new key
        var n = ecparams.getN();
        this.priv = ecdsa.getBigRandom(n);
        this.compressed = compressed || false;
    }
    else this.import(input,compressed)
};

ECKey.prototype.import = function (input,compressed) {
    function has(li,v) { return li.indexOf(v) >= 0 }
    function fromBin(x) { return BigInteger.fromByteArrayUnsigned(x) }
    this.priv =
          input instanceof ECKey                   ? input.priv
        : input instanceof BigInteger              ? input.mod(ecparams.getN())
        : Array.isArray(input)                     ? fromBin(input.slice(0,32))
        : typeof input != "string"                 ? null
        : input.length == 44                       ? fromBin(convert.base64ToBytes(input))
        : input.length == 51 && input[0] == '5'    ? fromBin(base58.checkDecode(input))
        : input.length == 51 && input[0] == '9'    ? fromBin(base58.checkDecode(input))
        : input.length == 52 && has('LK',input[0]) ? fromBin(base58.checkDecode(input).slice(0,32))
        : input.length == 52 && input[0] == 'c'    ? fromBin(base58.checkDecode(input).slice(0,32))
        : has([64,65],input.length)                ? fromBin(convert.hexToBytes(input.slice(0,64)))
                                                   : null

    this.compressed =
          compressed !== undefined                 ? compressed
        : input instanceof ECKey                   ? input.compressed
        : input instanceof BigInteger              ? false
        : Array.isArray(input)                     ? false
        : typeof input != "string"                 ? null
        : input.length == 44                       ? false
        : input.length == 51 && input[0] == '5'    ? false
        : input.length == 51 && input[0] == '9'    ? false
        : input.length == 52 && has('LK',input[0]) ? true
        : input.length == 52 && input[0] == 'c'    ? true
        : input.length == 64                       ? false
        : input.length == 65                       ? true
                                                   : null
};

ECKey.prototype.getPub = function(compressed) {
    if (compressed === undefined) compressed = this.compressed
    return ECPubKey(ecparams.getG().multiply(this.priv),compressed)
}

/**
 * @deprecated Reserved keyword, factory pattern. Use toHex, toBytes, etc.
 */
ECKey.prototype['export'] = function(format) {
    var format = format || 'hex'
    return this['to' + format.substr(0, 1).toUpperCase() + format.substr(1)]()
}

ECKey.prototype.toBin = function() {
    return convert.bytesToString(this.toBytes())
}

ECKey.version_bytes = {
  0: 128,
  111: 239
}

ECKey.prototype.toWif = function(version) {
    version = version || Network.mainnet.addressVersion;

    return base58.checkEncode(this.toBytes(), ECKey.version_bytes[version])
}

ECKey.prototype.toHex = function() {
    return convert.bytesToHex(this.toBytes())
}

ECKey.prototype.toBytes = function() {
    var bytes = this.priv.toByteArrayUnsigned();
    if (this.compressed) bytes.push(1)
    return bytes
}

ECKey.prototype.toBase64 = function() {
    return convert.bytesToBase64(this.toBytes())
}

ECKey.prototype.toString = ECKey.prototype.toHex

ECKey.prototype.getAddress = function(version) {
    return this.getPub().getAddress(version)
}

ECKey.prototype.add = function(key) {
    return ECKey(this.priv.add(ECKey(key).priv),this.compressed)
}

ECKey.prototype.multiply = function(key) {
    return ECKey(this.priv.multiply(ECKey(key).priv),this.compressed)
}

ECKey.prototype.sign = function(hash) {
  return ecdsa.sign(hash, this.priv);
}

ECKey.prototype.verify = function(hash, sig) {
  return this.getPub().verify(hash, sig)
}

var ECPubKey = function(input, compressed) {
  if (!(this instanceof ECPubKey)) {
    return new ECPubKey(input, compressed)
  }

  this.import(input,compressed)
}

ECPubKey.prototype.import = function(input, compressed) {
    var decode = function(x) { return ECPointFp.decodeFrom(ecparams.getCurve(), x) }

    this.pub =
          input instanceof ECPointFp ? input
        : input instanceof ECKey     ? ecparams.getG().multiply(input.priv)
        : input instanceof ECPubKey  ? input.pub
        : typeof input == "string"   ? decode(convert.hexToBytes(input))
        : Array.isArray(input)       ? decode(input)
                                     : null

    this.compressed =
          compressed                 ? compressed
        : input instanceof ECPointFp ? input.compressed
        : input instanceof ECPubKey  ? input.compressed
                                     : (this.pub[0] < 4)
}

ECPubKey.prototype.add = function(key) {
    return ECPubKey(this.pub.add(ECPubKey(key).pub), this.compressed)
}

ECPubKey.prototype.multiply = function(key) {
    return ECPubKey(this.pub.multiply(ECKey(key).priv), this.compressed)
}

ECPubKey.prototype['export'] = function(format) {
    var format = format || 'hex';
    return this['to' + format.substr(0, 1).toUpperCase() + format.substr(1)]()
}

ECPubKey.prototype.toBytes = function(compressed) {
    if (compressed === undefined) compressed = this.compressed
    return this.pub.getEncoded(compressed)
}

ECPubKey.prototype.toHex = function(compressed) {
    return convert.bytesToHex(this.toBytes(compressed))
}

ECPubKey.prototype.toBin = function(compressed) {
    return convert.bytesToString(this.toBytes(compressed))
}

ECPubKey.prototype.toWif = function(version) {
    version = version || Network.mainnet.addressVersion;

    return base58.checkEncode(this.toBytes(), version)
}

ECPubKey.prototype.toString = ECPubKey.prototype.toHex

ECPubKey.prototype.getAddress = function(version) {
    version = version || Network.mainnet.addressVersion;

    return new Address(util.sha256ripe160(this.toBytes()), version);
}

ECPubKey.prototype.verify = function(hash, sig) {
  return ecdsa.verify(hash, sig, this.toBytes())
}

module.exports = {
  ECKey: ECKey,
  ECPubKey: ECPubKey
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Worldcosplay download
// @namespace    http://devs.forumvi.com/
// @description  Download photo(s) on worldcosplay.net
// @version      2.0.1
// @icon         http://i.imgur.com/gJLjIzb.png
// @author       Zzbaivong
// @license      MIT
// @match        http://worldcosplay.net/*/photos*
// @match        http://worldcosplay.net/*/favorites*
// @match        http://worldcosplay.net/photo/*
// @match        http://worldcosplay.net/tag/*
// @match        http://worldcosplay.net/search/photos?*
// @match        http://worldcosplay.net/character/*
// @match        http://worldcosplay.net/title/*
// @match        http://worldcosplay.net/photos
// @match        http://worldcosplay.net/popular
// @match        http://worldcosplay.net/ranking/good*
// @match        http://worldcosplay.net/*/photo/*
// @match        http://worldcosplay.net/*/tag/*
// @match        http://worldcosplay.net/*/search/photos?*
// @match        http://worldcosplay.net/*/character/*
// @match        http://worldcosplay.net/*/title/*
// @match        http://worldcosplay.net/*/photos
// @match        http://worldcosplay.net/*/popular
// @match        http://worldcosplay.net/*/ranking/good*
// @match        https://worldcosplay.net/*/photos*
// @match        https://worldcosplay.net/*/favorites*
// @match        https://worldcosplay.net/photo/*
// @match        https://worldcosplay.net/tag/*
// @match        https://worldcosplay.net/search/photos?*
// @match        https://worldcosplay.net/character/*
// @match        https://worldcosplay.net/title/*
// @match        https://worldcosplay.net/photos
// @match        https://worldcosplay.net/popular
// @match        https://worldcosplay.net/ranking/good*
// @match        https://worldcosplay.net/*/photo/*
// @match        https://worldcosplay.net/*/tag/*
// @match        https://worldcosplay.net/*/search/photos?*
// @match        https://worldcosplay.net/*/character/*
// @match        https://worldcosplay.net/*/title/*
// @match        https://worldcosplay.net/*/photos
// @match        https://worldcosplay.net/*/popular
// @match        https://worldcosplay.net/*/ranking/good*
// @require      https://code.jquery.com/jquery-2.2.4.min.js
// @require      https://greasyfork.org/scripts/18532-filesaver/code/FileSaver.js?version=135609
// @require      https://greasyfork.org/scripts/5392-waitforkeyelements/code/WaitForKeyElements.js?version=115012
// @noframes
// @connect      self
// @supportURL   https://github.com/baivong/Userscript/issues
// @run-at       document-idle
// @grant        GM_xmlhttpRequest
// @grant        GM_download
// ==/UserScript==

(function ($, window, document, undefined) {
    'use strict';

    window.URL = window.URL || window.webkitURL;

    function downloadPhoto(el, url) {
        var photoName = url.replace(/.*\//g, '');
        if (typeof GM_download !== 'undefined') {
            GM_download({
                url: url,
                name: photoName,
                saveAs: false,
                onerror: function (err) {
                    console.error(err);
                }
            });
        } else {
            GM_xmlhttpRequest({
                method: 'GET',
                url: url,
                responseType: 'blob',
                onload: function (response) {
                    var blob = response.response;
                    $(el).attr({
                        href: window.URL.createObjectURL(blob),
                        download: photoName
                    }).off('click');
                    saveAs(blob, photoName);
                },
                onerror: function (err) {
                    console.error(err);
                }
            });
        }
    }

    if (/^(\/[a-z\-]+)?\/photo\/\d+$/.test(location.pathname)) {

        var $btn = $('', {
            href: '#download',
            'class': 'download-this-photo',
            html: '

'
        });
        $btn.on('click', function (e) {
            e.preventDefault();
            e.stopPropagation();
            downloadPhoto(this, $('#photoContainer').find('.img').attr('src'));
        });
        $btn.insertAfter('.side_buttons');

    } else {

        var addBtn = function () {
            $('.preview').not('.added-download-btn').each(function () {
                var $this = $(this),
                    $btn = $('', {
                        href: '#download',
                        'class': 'download-this-photo',
                        html: '

'
                    });
                $btn.on('click', function (e) {
                    e.preventDefault();
                    e.stopPropagation();
                    downloadPhoto(this, $this.find('.photo_img').css('backgroundImage').slice(5, -2).replace('sq300/', ''));
                });
                $this.find('.options').append($btn);
                $this.addClass('added-download-btn');
            });
        };
        addBtn();

        waitForKeyElements('.preview', addBtn);

    }

})(jQuery, window, document);
<commit_msg>Update libs, fix image size in album download<commit_after>// ==UserScript==
// @name         Worldcosplay download
// @namespace    http://devs.forumvi.com/
// @description  Download photo(s) on worldcosplay.net
// @version      2.1.0
// @icon         http://i.imgur.com/gJLjIzb.png
// @author       Zzbaivong
// @license      MIT
// @match        http://worldcosplay.net/*/photos*
// @match        http://worldcosplay.net/*/favorites*
// @match        http://worldcosplay.net/photo/*
// @match        http://worldcosplay.net/tag/*
// @match        http://worldcosplay.net/search/photos?*
// @match        http://worldcosplay.net/collections/*
// @match        http://worldcosplay.net/character/*
// @match        http://worldcosplay.net/title/*
// @match        http://worldcosplay.net/photos
// @match        http://worldcosplay.net/popular
// @match        http://worldcosplay.net/ranking/good*
// @match        http://worldcosplay.net/*/photo/*
// @match        http://worldcosplay.net/*/tag/*
// @match        http://worldcosplay.net/*/search/photos?*
// @match        http://worldcosplay.net/*/collections/*
// @match        http://worldcosplay.net/*/character/*
// @match        http://worldcosplay.net/*/title/*
// @match        http://worldcosplay.net/*/photos
// @match        http://worldcosplay.net/*/popular
// @match        http://worldcosplay.net/*/ranking/good*
// @match        https://worldcosplay.net/*/photos*
// @match        https://worldcosplay.net/*/favorites*
// @match        https://worldcosplay.net/photo/*
// @match        https://worldcosplay.net/tag/*
// @match        https://worldcosplay.net/search/photos?*
// @match        https://worldcosplay.net/collections/*
// @match        https://worldcosplay.net/character/*
// @match        https://worldcosplay.net/title/*
// @match        https://worldcosplay.net/photos
// @match        https://worldcosplay.net/popular
// @match        https://worldcosplay.net/ranking/good*
// @match        https://worldcosplay.net/*/photo/*
// @match        https://worldcosplay.net/*/tag/*
// @match        https://worldcosplay.net/*/search/photos?*
// @match        https://worldcosplay.net/*/collections/*
// @match        https://worldcosplay.net/*/character/*
// @match        https://worldcosplay.net/*/title/*
// @match        https://worldcosplay.net/*/photos
// @match        https://worldcosplay.net/*/popular
// @match        https://worldcosplay.net/*/ranking/good*
// @require      https://code.jquery.com/jquery-3.2.1.slim.min.js
// @require      https://greasyfork.org/scripts/18532-filesaver/code/FileSaver.js?version=164030
// @require      https://greasyfork.org/scripts/5392-waitforkeyelements/code/WaitForKeyElements.js?version=115012
// @noframes
// @connect      self
// @supportURL   https://github.com/baivong/Userscript/issues
// @run-at       document-idle
// @grant        GM_xmlhttpRequest
// @grant        GM_download
// ==/UserScript==

/* global GM_download, waitForKeyElements */
(function ($, window) {
    'use strict';

    window.URL = window.URL || window.webkitURL;

    function downloadPhoto(el, url) {
        var photoName = url.replace(/.*\//g, '');
        if (typeof GM_download !== 'undefined') {
            GM_download({
                url: url,
                name: photoName,
                saveAs: false,
                onerror: function (err) {
                    console.error(err);
                }
            });
        } else {
            GM_xmlhttpRequest({
                method: 'GET',
                url: url,
                responseType: 'blob',
                onload: function (response) {
                    var blob = response.response;
                    $(el).attr({
                        href: window.URL.createObjectURL(blob),
                        download: photoName
                    }).off('click');
                    saveAs(blob, photoName);
                },
                onerror: function (err) {
                    console.error(err);
                }
            });
        }
    }

    if (/^(\/[a-z\-]+)?\/photo\/\d+$/.test(location.pathname)) {

        var $btn = $('', {
            href: '#download',
            'class': 'download-this-photo',
            html: '

'
        });
        $btn.on('click', function (e) {
            e.preventDefault();
            e.stopPropagation();
            downloadPhoto(this, $('#photoContainer').find('.img').attr('src'));
        });
        $btn.insertAfter('.side_buttons');

    } else {

        var addBtn = function () {
            $('.preview').not('.added-download-btn').each(function () {
                var $this = $(this),
                    $btn = $('', {
                        href: '#download',
                        'class': 'download-this-photo',
                        html: '

'
                    });
                $btn.on('click', function (e) {
                    e.preventDefault();
                    e.stopPropagation();
                    downloadPhoto(this, $this.find('.photo_img').css('backgroundImage').slice(5, -2).replace('-350x600.', '-3000.'));
                });
                $this.find('.options').append($btn);
                $this.addClass('added-download-btn');
            });
        };
        addBtn();

        waitForKeyElements('.preview', addBtn);

    }

})(jQuery, window);
<|endoftext|>