This commit is contained in:
lalBi94
2023-03-05 13:23:23 +01:00
commit 7bc56c09b5
14034 changed files with 1834369 additions and 0 deletions

32
node_modules/spawn-wrap/lib/debug.js generated vendored Normal file
View File

@@ -0,0 +1,32 @@
'use strict';
const util = require('util');
const fs = require('fs')
/**
* Boolean indicating if debug mode is enabled.
*
* @type {boolean}
*/
const IS_DEBUG = process.env.SPAWN_WRAP_DEBUG === '1'
/**
* If debug is enabled, write message to stderr.
*
* If debug is disabled, no message is written.
*/
function debug(...args) {
if (!IS_DEBUG) {
return;
}
const prefix = `SW ${process.pid}: `
const data = util.format(...args).trim()
const message = data.split('\n').map(line => `${prefix}${line}\n`).join('')
fs.writeSync(2, message)
}
module.exports = {
IS_DEBUG,
debug,
}

53
node_modules/spawn-wrap/lib/exe-type.js generated vendored Normal file
View File

@@ -0,0 +1,53 @@
'use strict';
const isWindows = require("is-windows")
const path = require("path")
function isCmd(file) {
const comspec = path.basename(process.env.comspec || '').replace(/\.exe$/i, '')
return isWindows() && (file === comspec || /^cmd(?:\.exe)?$/i.test(file))
}
function isNode(file) {
const cmdname = path.basename(process.execPath).replace(/\.exe$/i, '')
return file === 'node' || cmdname === file
}
function isNpm(file) {
// XXX is this even possible/necessary?
// wouldn't npm just be detected as a node shebang?
return file === 'npm' && !isWindows()
}
function isSh(file) {
return ['dash', 'sh', 'bash', 'zsh'].includes(file)
}
/**
* Returns the basename of the executable.
*
* On Windows, strips the `.exe` extension (if any) and normalizes the name to
* lowercase.
*
* @param exePath {string} Path of the executable as passed to spawned processes:
* either command or a path to a file.
* @return {string} Basename of the executable.
*/
function getExeBasename(exePath) {
const baseName = path.basename(exePath);
if (isWindows()) {
// Stripping `.exe` seems to be enough for our usage. We may eventually
// want to handle all executable extensions (such as `.bat` or `.cmd`).
return baseName.replace(/\.exe$/i, "").toLowerCase();
} else {
return baseName;
}
}
module.exports = {
isCmd,
isNode,
isNpm,
isSh,
getExeBasename,
}

5
node_modules/spawn-wrap/lib/homedir.js generated vendored Normal file
View File

@@ -0,0 +1,5 @@
'use strict'
const os = require('os')
module.exports = process.env.SPAWN_WRAP_SHIM_ROOT || os.homedir()

84
node_modules/spawn-wrap/lib/munge.js generated vendored Normal file
View File

@@ -0,0 +1,84 @@
'use strict';
const {isCmd, isNode, isNpm, isSh, getExeBasename} = require("./exe-type")
const mungeCmd = require("./mungers/cmd")
const mungeEnv = require("./mungers/env")
const mungeNode = require("./mungers/node")
const mungeNpm = require("./mungers/npm")
const mungeSh = require("./mungers/sh")
const mungeShebang = require("./mungers/shebang")
/**
* @typedef {object} InternalSpawnOptions Options for the internal spawn functions
* `childProcess.ChildProcess.prototype.spawn` and `process.binding('spawn_sync').spawn`.
* These are the options mapped by the `munge` function to intercept spawned processes and
* handle the wrapping logic.
*
* @property {string} file File to execute: either an absolute system-dependent path or a
* command name.
* @property {string[]} args Command line arguments passed to the spawn process, including argv0.
* @property {string | undefined} cwd Optional path to the current working directory passed to the
* spawned process. Default: `process.cwd()`
* @property {boolean} windowsHide Boolean controlling if the process should be spawned as
* hidden (no GUI) on Windows.
* @property {boolean} windowsVerbatimArguments Boolean controlling if Node should preprocess
* the CLI arguments on Windows.
* @property {boolean} detached Boolean controlling if the child process should keep its parent
* alive or not.
* @property {string[]} envPairs Array of serialized environment variable key/value pairs. The
* variables serialized as `key + "=" + value`.
* @property {import("child_process").StdioOptions} stdio Stdio options, with the same semantics
* as the `stdio` parameter from the public API.
* @property {number | undefined} uid User id for the spawn process, same as the `uid` parameter
* from the public API.
* @property {number | undefined} gid Group id for the spawn process, same as the `gid` parameter
* from the public API.
*
* @property {string | undefined} originalNode Custom property only used by `spawn-wrap`. It is
* used to remember the original Node executable that was intended to be spawned by the user.
*/
/**
* Returns updated internal spawn options to redirect the process through the shim and wrapper.
*
* This works on the options passed to `childProcess.ChildProcess.prototype.spawn` and
* `process.binding('spawn_sync').spawn`.
*
* This function works by trying to identify the spawn process and map the options accordingly.
* `spawn-wrap` recognizes most shells, Windows `cmd.exe`, Node and npm invocations; when spawn
* either directly or through a script with a shebang line.
* It also unconditionally updates the environment variables so bare `node` commands execute
* the shim script instead of Node's binary.
*
* @param workingDir {string} Absolute system-dependent path to the directory containing the shim files.
* @param options {InternalSpawnOptions} Original internal spawn options.
* @return {InternalSpawnOptions} Updated internal spawn options.
*/
function munge(workingDir, options) {
const basename = getExeBasename(options.file);
// XXX: dry this
if (isSh(basename)) {
options = mungeSh(workingDir, options)
} else if (isCmd(basename)) {
options = mungeCmd(workingDir, options)
} else if (isNode(basename)) {
options = mungeNode(workingDir, options)
} else if (isNpm(basename)) {
// XXX unnecessary? on non-windows, npm is just another shebang
options = mungeNpm(workingDir, options)
} else {
options = mungeShebang(workingDir, options)
}
// now the options are munged into shape.
// whether we changed something or not, we still update the PATH
// so that if a script somewhere calls `node foo`, it gets our
// wrapper instead.
options = mungeEnv(workingDir, options)
return options
}
module.exports = munge

59
node_modules/spawn-wrap/lib/mungers/cmd.js generated vendored Normal file
View File

@@ -0,0 +1,59 @@
'use strict';
const path = require("path")
const whichOrUndefined = require("../which-or-undefined")
/**
* Intercepts Node and npm processes spawned through Windows' `cmd.exe`.
*
* @param workingDir {string} Absolute system-dependent path to the directory containing the shim files.
* @param options {import("../munge").InternalSpawnOptions} Original internal spawn options.
* @return {import("../munge").InternalSpawnOptions} Updated internal spawn options.
*/
function mungeCmd(workingDir, options) {
const cmdi = options.args.indexOf('/c')
if (cmdi === -1) {
return {...options}
}
const re = /^\s*("*)([^"]*?\bnode(?:\.exe|\.EXE)?)("*)( .*)?$/
const npmre = /^\s*("*)([^"]*?\b(?:npm))("*)( |$)/
const command = options.args[cmdi + 1]
if (command === undefined) {
return {...options}
}
let newArgs = [...options.args];
// Remember the original Node command to use it in the shim
let originalNode;
let m = command.match(re)
let replace
if (m) {
originalNode = m[2]
// TODO: Remove `replace`: seems unused
replace = m[1] + path.join(workingDir, 'node.cmd') + m[3] + m[4]
newArgs[cmdi + 1] = m[1] + m[2] + m[3] +
' "' + path.join(workingDir, 'node') + '"' + m[4]
} else {
// XXX probably not a good idea to rewrite to the first npm in the
// path if it's a full path to npm. And if it's not a full path to
// npm, then the dirname will not work properly!
m = command.match(npmre)
if (m === null) {
return {...options}
}
let npmPath = whichOrUndefined('npm') || 'npm'
npmPath = path.join(path.dirname(npmPath), 'node_modules', 'npm', 'bin', 'npm-cli.js')
replace = m[1] + '"' + path.join(workingDir, 'node.cmd') + '"' +
' "' + npmPath + '"' +
m[3] + m[4]
newArgs[cmdi + 1] = command.replace(npmre, replace)
}
return {...options, args: newArgs, originalNode};
}
module.exports = mungeCmd

49
node_modules/spawn-wrap/lib/mungers/env.js generated vendored Normal file
View File

@@ -0,0 +1,49 @@
'use strict';
const isWindows = require("is-windows")
const path = require("path")
const homedir = require("../homedir")
const pathRe = isWindows() ? /^PATH=/i : /^PATH=/;
/**
* Updates the environment variables to intercept `node` commands and pass down options.
*
* @param workingDir {string} Absolute system-dependent path to the directory containing the shim files.
* @param options {import("../munge").InternalSpawnOptions} Original internal spawn options.
* @return {import("../munge").InternalSpawnOptions} Updated internal spawn options.
*/
function mungeEnv(workingDir, options) {
let pathEnv
const envPairs = options.envPairs.map((ep) => {
if (pathRe.test(ep)) {
// `PATH` env var: prefix its value with `workingDir`
// `5` corresponds to the length of `PATH=`
pathEnv = ep.substr(5)
const k = ep.substr(0, 5)
return k + workingDir + path.delimiter + pathEnv
} else {
// Return as-is
return ep;
}
});
if (pathEnv === undefined) {
envPairs.push((isWindows() ? 'Path=' : 'PATH=') + workingDir)
}
if (options.originalNode) {
const key = path.basename(workingDir).substr('.node-spawn-wrap-'.length)
envPairs.push('SW_ORIG_' + key + '=' + options.originalNode)
}
envPairs.push('SPAWN_WRAP_SHIM_ROOT=' + homedir)
if (process.env.SPAWN_WRAP_DEBUG === '1') {
envPairs.push('SPAWN_WRAP_DEBUG=1')
}
return {...options, envPairs};
}
module.exports = mungeEnv

79
node_modules/spawn-wrap/lib/mungers/node.js generated vendored Normal file
View File

@@ -0,0 +1,79 @@
'use strict';
const path = require('path')
const {debug} = require("../debug")
const {getExeBasename} = require("../exe-type")
const whichOrUndefined = require("../which-or-undefined")
/**
* Intercepts Node spawned processes.
*
* @param workingDir {string} Absolute system-dependent path to the directory containing the shim files.
* @param options {import("../munge").InternalSpawnOptions} Original internal spawn options.
* @return {import("../munge").InternalSpawnOptions} Updated internal spawn options.
*/
function mungeNode(workingDir, options) {
// Remember the original Node command to use it in the shim
const originalNode = options.file
const command = getExeBasename(options.file)
// make sure it has a main script.
// otherwise, just let it through.
let a = 0
let hasMain = false
let mainIndex = 1
for (a = 1; !hasMain && a < options.args.length; a++) {
switch (options.args[a]) {
case '-p':
case '-i':
case '--interactive':
case '--eval':
case '-e':
case '-pe':
hasMain = false
a = options.args.length
continue
case '-r':
case '--require':
a += 1
continue
default:
// TODO: Double-check this part
if (options.args[a].startsWith('-')) {
continue
} else {
hasMain = true
mainIndex = a
a = options.args.length
break
}
}
}
const newArgs = [...options.args];
let newFile = options.file;
if (hasMain) {
const replace = path.join(workingDir, command)
newArgs.splice(mainIndex, 0, replace)
}
// If the file is just something like 'node' then that'll
// resolve to our shim, and so to prevent double-shimming, we need
// to resolve that here first.
// This also handles the case where there's not a main file, like
// `node -e 'program'`, where we want to avoid the shim entirely.
if (options.file === command) {
const realNode = whichOrUndefined(options.file) || process.execPath
newArgs[0] = realNode
newFile = realNode
}
debug('mungeNode after', options.file, options.args)
return {...options, file: newFile, args: newArgs, originalNode};
}
module.exports = mungeNode

32
node_modules/spawn-wrap/lib/mungers/npm.js generated vendored Normal file
View File

@@ -0,0 +1,32 @@
'use strict';
const path = require("path")
const {debug} = require("../debug")
const whichOrUndefined = require("../which-or-undefined")
/**
* Intercepts npm spawned processes.
*
* @param workingDir {string} Absolute system-dependent path to the directory containing the shim files.
* @param options {import("../munge").InternalSpawnOptions} Original internal spawn options.
* @return {import("../munge").InternalSpawnOptions} Updated internal spawn options.
*/
function mungeNpm(workingDir, options) {
debug('munge npm')
// XXX weird effects of replacing a specific npm with a global one
const npmPath = whichOrUndefined('npm')
if (npmPath === undefined) {
return {...options};
}
const newArgs = [...options.args]
newArgs[0] = npmPath
const file = path.join(workingDir, 'node')
newArgs.unshift(file)
return {...options, file, args: newArgs}
}
module.exports = mungeNpm

61
node_modules/spawn-wrap/lib/mungers/sh.js generated vendored Normal file
View File

@@ -0,0 +1,61 @@
'use strict';
const isWindows = require("is-windows")
const path = require("path")
const {debug} = require("../debug")
const {isNode} = require("../exe-type")
const whichOrUndefined = require("../which-or-undefined")
/**
* Intercepts Node and npm processes spawned through a Linux shell.
*
* @param workingDir {string} Absolute system-dependent path to the directory containing the shim files.
* @param options {import("../munge").InternalSpawnOptions} Original internal spawn options.
* @return {import("../munge").InternalSpawnOptions} Updated internal spawn options.
*/
function mungeSh(workingDir, options) {
const cmdi = options.args.indexOf('-c')
if (cmdi === -1) {
return {...options} // no -c argument
}
let c = options.args[cmdi + 1]
const re = /^\s*((?:[^\= ]*\=[^\=\s]*)*[\s]*)([^\s]+|"[^"]+"|'[^']+')( .*)?$/
const match = c.match(re)
if (match === null) {
return {...options} // not a command invocation. weird but possible
}
let command = match[2]
// strip quotes off the command
const quote = command.charAt(0)
if ((quote === '"' || quote === '\'') && command.endsWith(quote)) {
command = command.slice(1, -1)
}
const exe = path.basename(command)
let newArgs = [...options.args];
// Remember the original Node command to use it in the shim
let originalNode;
const workingNode = path.join(workingDir, 'node')
if (isNode(exe)) {
originalNode = command
c = `${match[1]}${match[2]} "${workingNode}" ${match[3]}`
newArgs[cmdi + 1] = c
} else if (exe === 'npm' && !isWindows()) {
// XXX this will exhibit weird behavior when using /path/to/npm,
// if some other npm is first in the path.
const npmPath = whichOrUndefined('npm')
if (npmPath) {
c = c.replace(re, `$1 "${workingNode}" "${npmPath}" $3`)
newArgs[cmdi + 1] = c
debug('npm munge!', c)
}
}
return {...options, args: newArgs, originalNode};
}
module.exports = mungeSh

43
node_modules/spawn-wrap/lib/mungers/shebang.js generated vendored Normal file
View File

@@ -0,0 +1,43 @@
'use strict';
const fs = require("fs")
const path = require("path")
const {isNode} = require("../exe-type")
const whichOrUndefined = require("../which-or-undefined")
/**
* Intercepts processes spawned through a script with a shebang line.
*
* @param workingDir {string} Absolute system-dependent path to the directory containing the shim files.
* @param options {import("../munge").InternalSpawnOptions} Original internal spawn options.
* @return {import("../munge").InternalSpawnOptions} Updated internal spawn options.
*/
function mungeShebang(workingDir, options) {
const resolved = whichOrUndefined(options.file)
if (resolved === undefined) {
return {...options}
}
const shebang = fs.readFileSync(resolved, 'utf8')
const match = shebang.match(/^#!([^\r\n]+)/)
if (!match) {
return {...options} // not a shebang script, probably a binary
}
const shebangbin = match[1].split(' ')[0]
const maybeNode = path.basename(shebangbin)
if (!isNode(maybeNode)) {
return {...options} // not a node shebang, leave untouched
}
const originalNode = shebangbin
const file = shebangbin
const args = [shebangbin, path.join(workingDir, maybeNode)]
.concat(resolved)
.concat(match[1].split(' ').slice(1))
.concat(options.args.slice(1))
return {...options, file, args, originalNode};
}
module.exports = mungeShebang

12
node_modules/spawn-wrap/lib/which-or-undefined.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
'use strict';
const which = require("which")
function whichOrUndefined(executable) {
try {
return which.sync(executable)
} catch (error) {
}
}
module.exports = whichOrUndefined