diff options
Diffstat (limited to 'node_modules/cross-spawn/lib')
| -rw-r--r-- | node_modules/cross-spawn/lib/enoent.js | 73 | ||||
| -rw-r--r-- | node_modules/cross-spawn/lib/parse.js | 113 | ||||
| -rw-r--r-- | node_modules/cross-spawn/lib/util/escapeArgument.js | 30 | ||||
| -rw-r--r-- | node_modules/cross-spawn/lib/util/escapeCommand.js | 12 | ||||
| -rw-r--r-- | node_modules/cross-spawn/lib/util/hasEmptyArgumentBug.js | 18 | ||||
| -rw-r--r-- | node_modules/cross-spawn/lib/util/readShebang.js | 37 | ||||
| -rw-r--r-- | node_modules/cross-spawn/lib/util/resolveCommand.js | 31 | 
7 files changed, 314 insertions, 0 deletions
diff --git a/node_modules/cross-spawn/lib/enoent.js b/node_modules/cross-spawn/lib/enoent.js new file mode 100644 index 0000000..d0a193a --- /dev/null +++ b/node_modules/cross-spawn/lib/enoent.js @@ -0,0 +1,73 @@ +'use strict'; + +var isWin = process.platform === 'win32'; +var resolveCommand = require('./util/resolveCommand'); + +var isNode10 = process.version.indexOf('v0.10.') === 0; + +function notFoundError(command, syscall) { +    var err; + +    err = new Error(syscall + ' ' + command + ' ENOENT'); +    err.code = err.errno = 'ENOENT'; +    err.syscall = syscall + ' ' + command; + +    return err; +} + +function hookChildProcess(cp, parsed) { +    var originalEmit; + +    if (!isWin) { +        return; +    } + +    originalEmit = cp.emit; +    cp.emit = function (name, arg1) { +        var err; + +        // If emitting "exit" event and exit code is 1, we need to check if +        // the command exists and emit an "error" instead +        // See: https://github.com/IndigoUnited/node-cross-spawn/issues/16 +        if (name === 'exit') { +            err = verifyENOENT(arg1, parsed, 'spawn'); + +            if (err) { +                return originalEmit.call(cp, 'error', err); +            } +        } + +        return originalEmit.apply(cp, arguments); +    }; +} + +function verifyENOENT(status, parsed) { +    if (isWin && status === 1 && !parsed.file) { +        return notFoundError(parsed.original, 'spawn'); +    } + +    return null; +} + +function verifyENOENTSync(status, parsed) { +    if (isWin && status === 1 && !parsed.file) { +        return notFoundError(parsed.original, 'spawnSync'); +    } + +    // If we are in node 10, then we are using spawn-sync; if it exited +    // with -1 it probably means that the command does not exist +    if (isNode10 && status === -1) { +        parsed.file = isWin ? parsed.file : resolveCommand(parsed.original); + +        if (!parsed.file) { +            return notFoundError(parsed.original, 'spawnSync'); +        } +    } + +    return null; +} + +module.exports.hookChildProcess = hookChildProcess; +module.exports.verifyENOENT = verifyENOENT; +module.exports.verifyENOENTSync = verifyENOENTSync; +module.exports.notFoundError = notFoundError; diff --git a/node_modules/cross-spawn/lib/parse.js b/node_modules/cross-spawn/lib/parse.js new file mode 100644 index 0000000..10a0136 --- /dev/null +++ b/node_modules/cross-spawn/lib/parse.js @@ -0,0 +1,113 @@ +'use strict'; + +var resolveCommand = require('./util/resolveCommand'); +var hasEmptyArgumentBug = require('./util/hasEmptyArgumentBug'); +var escapeArgument = require('./util/escapeArgument'); +var escapeCommand = require('./util/escapeCommand'); +var readShebang = require('./util/readShebang'); + +var isWin = process.platform === 'win32'; +var skipShellRegExp = /\.(?:com|exe)$/i; + +// Supported in Node >= 6 and >= 4.8 +var supportsShellOption = parseInt(process.version.substr(1).split('.')[0], 10) >= 6 || + parseInt(process.version.substr(1).split('.')[0], 10) === 4 && parseInt(process.version.substr(1).split('.')[1], 10) >= 8; + +function parseNonShell(parsed) { +    var shebang; +    var needsShell; +    var applyQuotes; + +    if (!isWin) { +        return parsed; +    } + +    // Detect & add support for shebangs +    parsed.file = resolveCommand(parsed.command); +    parsed.file = parsed.file || resolveCommand(parsed.command, true); +    shebang = parsed.file && readShebang(parsed.file); + +    if (shebang) { +        parsed.args.unshift(parsed.file); +        parsed.command = shebang; +        needsShell = hasEmptyArgumentBug || !skipShellRegExp.test(resolveCommand(shebang) || resolveCommand(shebang, true)); +    } else { +        needsShell = hasEmptyArgumentBug || !skipShellRegExp.test(parsed.file); +    } + +    // If a shell is required, use cmd.exe and take care of escaping everything correctly +    if (needsShell) { +        // Escape command & arguments +        applyQuotes = (parsed.command !== 'echo');  // Do not quote arguments for the special "echo" command +        parsed.command = escapeCommand(parsed.command); +        parsed.args = parsed.args.map(function (arg) { +            return escapeArgument(arg, applyQuotes); +        }); + +        // Make use of cmd.exe +        parsed.args = ['/d', '/s', '/c', '"' + parsed.command + (parsed.args.length ? ' ' + parsed.args.join(' ') : '') + '"']; +        parsed.command = process.env.comspec || 'cmd.exe'; +        parsed.options.windowsVerbatimArguments = true;  // Tell node's spawn that the arguments are already escaped +    } + +    return parsed; +} + +function parseShell(parsed) { +    var shellCommand; + +    // If node supports the shell option, there's no need to mimic its behavior +    if (supportsShellOption) { +        return parsed; +    } + +    // Mimic node shell option, see: https://github.com/nodejs/node/blob/b9f6a2dc059a1062776133f3d4fd848c4da7d150/lib/child_process.js#L335 +    shellCommand = [parsed.command].concat(parsed.args).join(' '); + +    if (isWin) { +        parsed.command = typeof parsed.options.shell === 'string' ? parsed.options.shell : process.env.comspec || 'cmd.exe'; +        parsed.args = ['/d', '/s', '/c', '"' + shellCommand + '"']; +        parsed.options.windowsVerbatimArguments = true;  // Tell node's spawn that the arguments are already escaped +    } else { +        if (typeof parsed.options.shell === 'string') { +            parsed.command = parsed.options.shell; +        } else if (process.platform === 'android') { +            parsed.command = '/system/bin/sh'; +        } else { +            parsed.command = '/bin/sh'; +        } + +        parsed.args = ['-c', shellCommand]; +    } + +    return parsed; +} + +// ------------------------------------------------ + +function parse(command, args, options) { +    var parsed; + +    // Normalize arguments, similar to nodejs +    if (args && !Array.isArray(args)) { +        options = args; +        args = null; +    } + +    args = args ? args.slice(0) : [];  // Clone array to avoid changing the original +    options = options || {}; + +    // Build our parsed object +    parsed = { +        command: command, +        args: args, +        options: options, +        file: undefined, +        original: command, +    }; + +    // Delegate further parsing to shell or non-shell +    return options.shell ? parseShell(parsed) : parseNonShell(parsed); +} + +module.exports = parse; diff --git a/node_modules/cross-spawn/lib/util/escapeArgument.js b/node_modules/cross-spawn/lib/util/escapeArgument.js new file mode 100644 index 0000000..367263f --- /dev/null +++ b/node_modules/cross-spawn/lib/util/escapeArgument.js @@ -0,0 +1,30 @@ +'use strict'; + +function escapeArgument(arg, quote) { +    // Convert to string +    arg = '' + arg; + +    // If we are not going to quote the argument, +    // escape shell metacharacters, including double and single quotes: +    if (!quote) { +        arg = arg.replace(/([()%!^<>&|;,"'\s])/g, '^$1'); +    } else { +        // Sequence of backslashes followed by a double quote: +        // double up all the backslashes and escape the double quote +        arg = arg.replace(/(\\*)"/g, '$1$1\\"'); + +        // Sequence of backslashes followed by the end of the string +        // (which will become a double quote later): +        // double up all the backslashes +        arg = arg.replace(/(\\*)$/, '$1$1'); + +        // All other backslashes occur literally + +        // Quote the whole thing: +        arg = '"' + arg + '"'; +    } + +    return arg; +} + +module.exports = escapeArgument; diff --git a/node_modules/cross-spawn/lib/util/escapeCommand.js b/node_modules/cross-spawn/lib/util/escapeCommand.js new file mode 100644 index 0000000..d9c25b2 --- /dev/null +++ b/node_modules/cross-spawn/lib/util/escapeCommand.js @@ -0,0 +1,12 @@ +'use strict'; + +var escapeArgument = require('./escapeArgument'); + +function escapeCommand(command) { +    // Do not escape if this command is not dangerous.. +    // We do this so that commands like "echo" or "ifconfig" work +    // Quoting them, will make them unaccessible +    return /^[a-z0-9_-]+$/i.test(command) ? command : escapeArgument(command, true); +} + +module.exports = escapeCommand; diff --git a/node_modules/cross-spawn/lib/util/hasEmptyArgumentBug.js b/node_modules/cross-spawn/lib/util/hasEmptyArgumentBug.js new file mode 100644 index 0000000..9f2eba6 --- /dev/null +++ b/node_modules/cross-spawn/lib/util/hasEmptyArgumentBug.js @@ -0,0 +1,18 @@ +'use strict'; + +// See: https://github.com/IndigoUnited/node-cross-spawn/pull/34#issuecomment-221623455 +function hasEmptyArgumentBug() { +    var nodeVer; + +    if (process.platform !== 'win32') { +        return false; +    } + +    nodeVer = process.version.substr(1).split('.').map(function (num) { +        return parseInt(num, 10); +    }); + +    return (nodeVer[0] === 0 && nodeVer[1] < 12); +} + +module.exports = hasEmptyArgumentBug(); diff --git a/node_modules/cross-spawn/lib/util/readShebang.js b/node_modules/cross-spawn/lib/util/readShebang.js new file mode 100644 index 0000000..2cf3541 --- /dev/null +++ b/node_modules/cross-spawn/lib/util/readShebang.js @@ -0,0 +1,37 @@ +'use strict'; + +var fs = require('fs'); +var LRU = require('lru-cache'); +var shebangCommand = require('shebang-command'); + +var shebangCache = new LRU({ max: 50, maxAge: 30 * 1000 });  // Cache just for 30sec + +function readShebang(command) { +    var buffer; +    var fd; +    var shebang; + +    // Check if it is in the cache first +    if (shebangCache.has(command)) { +        return shebangCache.get(command); +    } + +    // Read the first 150 bytes from the file +    buffer = new Buffer(150); + +    try { +        fd = fs.openSync(command, 'r'); +        fs.readSync(fd, buffer, 0, 150, 0); +        fs.closeSync(fd); +    } catch (e) { /* empty */ } + +    // Attempt to extract shebang (null is returned if not a shebang) +    shebang = shebangCommand(buffer.toString()); + +    // Store the shebang in the cache +    shebangCache.set(command, shebang); + +    return shebang; +} + +module.exports = readShebang; diff --git a/node_modules/cross-spawn/lib/util/resolveCommand.js b/node_modules/cross-spawn/lib/util/resolveCommand.js new file mode 100644 index 0000000..b7a9490 --- /dev/null +++ b/node_modules/cross-spawn/lib/util/resolveCommand.js @@ -0,0 +1,31 @@ +'use strict'; + +var path = require('path'); +var which = require('which'); +var LRU = require('lru-cache'); + +var commandCache = new LRU({ max: 50, maxAge: 30 * 1000 });  // Cache just for 30sec + +function resolveCommand(command, noExtension) { +    var resolved; + +    noExtension = !!noExtension; +    resolved = commandCache.get(command + '!' + noExtension); + +    // Check if its resolved in the cache +    if (commandCache.has(command)) { +        return commandCache.get(command); +    } + +    try { +        resolved = !noExtension ? +            which.sync(command) : +            which.sync(command, { pathExt: path.delimiter + (process.env.PATHEXT || '') }); +    } catch (e) { /* empty */ } + +    commandCache.set(command + '!' + noExtension, resolved); + +    return resolved; +} + +module.exports = resolveCommand;  | 
