Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const assert = require('node:assert/strict');
const { execFileSync } = require('node:child_process');
const path = require('node:path');

const tools = (process.env.VP_PATH_INJECTED_TOOLS || '').split(',');
assert.ok(tools.includes('pnpm'));
assert.ok(tools.includes('pnpx'));
const shim = path.join(process.env.VP_HOME, 'bin', 'pnpm');
assert.equal(execFileSync(shim, ['--version'], { encoding: 'utf8' }).trim(), '10.19.0');
console.log('Workspace exec preserves injected pnpm');
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,13 @@ steps = [
{ argv = ["vp", "exec", "-r", "--report-summary", "--", "node", "-e", "console.log(process.env.VP_PACKAGE_NAME)"], comment = "report summary", continue-on-failure = true },
{ argv = ["node", "-e", "const r=JSON.parse(require('fs').readFileSync('vp-exec-summary.json','utf8'));const s=r.executionStatus;for(const[k,v]of Object.entries(s)){console.log(k+': '+v.status+' '+(typeof v.duration==='number'?'has_duration':'no_duration'))}"], comment = "verify summary file", continue-on-failure = true },
]

[[case]]
name = "workspace_exec_propagates_injected_tools"
vp = ["local", "global"]
skip-platforms = ["windows"]
steps = [
{ argv = ["vpt", "json-edit", "package.json", "packageManager", "pnpm@10.19.0"], snapshot = false },
{ argv = ["vp", "exec", "--filter", "app-*", "--", "node", "../../assert-injected-pnpm.cjs"], comment = "Sequential workspace execution carries the package-manager PATH and its tool set" },
{ argv = ["vp", "exec", "--filter", "app-*", "--parallel", "--", "node", "../../assert-injected-pnpm.cjs"], comment = "Parallel workspace execution carries the same environment" },
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# workspace_exec_propagates_injected_tools

## `vpt json-edit package.json packageManager pnpm@10.19.0`


## `vp exec --filter app-* -- node ../../assert-injected-pnpm.cjs`

Sequential workspace execution carries the package-manager PATH and its tool set

```
VITE+ - The Unified Toolchain for the Web

app-a$ node ../../assert-injected-pnpm.cjs
Workspace exec preserves injected pnpm
app-b$ node ../../assert-injected-pnpm.cjs
Workspace exec preserves injected pnpm
```

## `vp exec --filter app-* --parallel -- node ../../assert-injected-pnpm.cjs`

Parallel workspace execution carries the same environment

```
VITE+ - The Unified Toolchain for the Web

app-a$ node ../../assert-injected-pnpm.cjs
Workspace exec preserves injected pnpm
app-b$ node ../../assert-injected-pnpm.cjs
Workspace exec preserves injected pnpm
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# workspace_exec_propagates_injected_tools

## `vpt json-edit package.json packageManager pnpm@10.19.0`


## `vp exec --filter app-* -- node ../../assert-injected-pnpm.cjs`

Sequential workspace execution carries the package-manager PATH and its tool set

```
app-a$ node ../../assert-injected-pnpm.cjs
Workspace exec preserves injected pnpm
app-b$ node ../../assert-injected-pnpm.cjs
Workspace exec preserves injected pnpm
```

## `vp exec --filter app-* --parallel -- node ../../assert-injected-pnpm.cjs`

Parallel workspace execution carries the same environment

```
app-a$ node ../../assert-injected-pnpm.cjs
Workspace exec preserves injected pnpm
app-b$ node ../../assert-injected-pnpm.cjs
Workspace exec preserves injected pnpm
```
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,14 @@ steps = [
{ argv = ["vpx", "--help"], comment = "should show vpx help message", continue-on-failure = true },
{ argv = ["vpx", "-s", "cowsay", "hello"], comment = "should run cowsay via dlx fallback", continue-on-failure = true },
]

[[case]]
name = "vpx_system_command_preserves_local_bin_path"
vp = "global"
skip-platforms = ["windows"]
steps = [
{ argv = ["vpt", "mkdir", "-p", "node_modules/.bin"], snapshot = false },
{ argv = ["vpt", "write-file", "node_modules/.bin/probe", "#!/bin/sh\necho local-probe\n"], snapshot = false },
{ argv = ["vpt", "chmod", "+x", "node_modules/.bin/probe"], snapshot = false },
{ argv = ["vpx", "sh", "-c", "probe"], comment = "System commands launched through vpx can still spawn project-local binaries" },
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# vpx_system_command_preserves_local_bin_path

## `vpt mkdir -p node_modules/.bin`


## `vpt write-file node_modules/.bin/probe '#'\!'/bin/sh
echo local-probe
'`


## `vpt chmod +x node_modules/.bin/probe`


## `vpx sh -c probe`

System commands launched through vpx can still spawn project-local binaries

```
local-probe
```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20.18.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const assert = require('node:assert/strict');
const { execFileSync } = require('node:child_process');
const { mkdirSync, writeFileSync } = require('node:fs');

assert.equal(process.version, 'v20.18.0');
assert.ok(process.env.VP_PATH_INJECTED_TOOLS.split(',').includes('node'));
const mode = process.argv[2];
const args = ['env', 'exec', 'node', '--version'];
const env = { ...process.env };
if (mode === 'project') {
mkdirSync('project-b');
writeFileSync('project-b/.node-version', '22.18.0');
writeFileSync('project-b/package.json', '{}');
args.unshift('-C', 'project-b');
} else {
env.VP_NODE_VERSION = '22.18.0';
}
if (mode === 'wrapper') {
env.VP_SHIM_WRAPPER = '1';
args.splice(3, 0, '--');
}
const version = execFileSync('vp', args, { env, encoding: 'utf8' }).trim();
assert.equal(version, mode === 'wrapper' ? 'v20.18.0' : 'v22.18.0');
console.log(`env exec ${mode}: ${version}`);
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const assert = require('node:assert/strict');
const { execSync } = require('node:child_process');

assert.equal(process.version, 'v22.18.0');
for (const tool of ['npm', 'npx']) {
assert.equal(execSync(`${tool} --version`, { encoding: 'utf8' }).trim(), '10.5.0');
}

if (process.argv[2] === 'child') {
assert.equal(execSync('pnpm --version', { encoding: 'utf8' }).trim(), '10.19.0');
console.log('Adding pnpm preserves inherited Node 22.18.0 and npm/npx 10.5.0');
} else {
execSync('pnpm exec node ../assert-inherited-npm.cjs child', {
cwd: 'pnpm-child',
stdio: 'inherit',
timeout: 30000,
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const assert = require('node:assert/strict');
const { execFileSync } = require('node:child_process');
const { copyFileSync, mkdirSync, writeFileSync } = require('node:fs');
const path = require('node:path');

assert.ok(process.env.VP_PATH_INJECTED_TOOLS.split(',').includes('node'));
const bin = path.join(process.env.VP_HOME, 'bin');
const paths = [bin];
if (process.argv[2] === 'trampoline') {
const other = path.resolve('other-installation');
mkdirSync(other);
const exe = path.join(other, process.platform === 'win32' ? 'node.exe' : 'node');
if (process.platform === 'win32') {
copyFileSync(path.join(bin, 'node.exe'), exe);
} else {
writeFileSync(exe, '#!/bin/sh\necho "Unexpected trampoline execution" >&2\nexit 99\n', {
mode: 0o755,
});
}
writeFileSync(
path.join(other, 'node.shim'),
`vite-plus-shim-v1\nlayout=single-root\ndata=${process.env.VP_HOME}\n`,
);
paths.push(other, path.dirname(process.execPath));
}
const version = execFileSync('node', ['--version'], {
env: { ...process.env, PATH: paths.join(path.delimiter) },
encoding: 'utf8',
timeout: 10000,
}).trim();
assert.equal(version, process.version);
console.log(`Node selection survives ${process.argv[2]} PATH`);
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const assert = require('node:assert/strict');
const { execFileSync } = require('node:child_process');
const { mkdirSync, symlinkSync, writeFileSync } = require('node:fs');
const path = require('node:path');

assert.equal(process.version, 'v22.18.0');
if (process.argv[2] === 'setup') {
mkdirSync('manager');
mkdirSync('system-shims');
const runtime = path.dirname(process.execPath).replaceAll("'", "'\\''");
writeFileSync(
'manager/tool-manager',
`#!/bin/sh\nexec '${runtime}/'"\${0##*/}" "$@"\n`,
{ mode: 0o755 },
);
for (const tool of ['vp', 'node', 'npm', 'npx']) {
symlinkSync('../manager/tool-manager', `system-shims/${tool}`);
}
} else {
assert.equal(process.env.VP_BYPASS, undefined);
assert.equal(
execFileSync('node', ['--version'], { encoding: 'utf8', timeout: 10000 }).trim(),
process.version,
);
const preload = process.argv[2] === 'preload';
const options = {
encoding: 'utf8',
timeout: 10000,
env: preload
? { ...process.env, NODE_OPTIONS: '--require ./preload-output.cjs' }
: process.env,
};
for (const tool of ['npm', 'npx']) {
assert.equal(
execFileSync(tool, ['--version'], options).trim(),
preload ? 'preload start\n10.9.3\npreload exit' : '10.9.3',
);
const args = ['--offline', '--call', 'node -e "console.log(process.version)"'];
if (tool === 'npm') args.unshift('exec');
assert.equal(
execFileSync(tool, args, options).trim(),
preload
? `preload start\npreload start\n${process.version}\npreload exit\npreload exit`
: process.version,
);
}
console.log('Bundled npm/npx use the runtime behind the system Node shim');
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const assert = require('node:assert/strict');
const { execFileSync } = require('node:child_process');
const { copyFileSync, mkdirSync, symlinkSync } = require('node:fs');
const path = require('node:path');

const mode = process.argv[2];
assert.equal(process.version, mode === 'system' ? 'v20.18.0' : 'v22.18.0');
const bin = path.join(process.env.VP_HOME, 'bin');
const paths = [];
if (mode === 'multiple') {
for (const name of ['installation-a', 'installation-b']) {
const dir = path.resolve(name);
mkdirSync(dir);
copyFileSync(path.join(bin, 'vp'), path.join(dir, 'vp'));
symlinkSync('vp', path.join(dir, 'node'));
paths.push(dir);
}
paths.push(path.dirname(process.execPath));
} else {
const dir = path.resolve('node-only');
mkdirSync(dir);
symlinkSync(process.execPath, path.join(dir, 'node'));
paths.push(bin, dir);
if (mode === 'system') {
const systemNode = execFileSync(
'vp',
['env', 'exec', '--node', '22.18.0', 'node', '-p', 'process.execPath'],
{ encoding: 'utf8' },
).trim();
paths.push(path.dirname(systemNode));
}
paths.push('/usr/bin', '/bin');
}
const env = { ...process.env, PATH: paths.join(path.delimiter) };
if (mode === 'system') {
// Only the selected Node is inherited; npm/npx now come from another runtime.
env.VP_PATH_INJECTED_TOOLS = 'node';
}
const version = execFileSync('node', ['--version'], {
env,
encoding: 'utf8',
timeout: 10000,
}).trim();
assert.equal(version, process.version);
if (mode === 'partial') {
for (const tool of ['npm', 'npx']) {
assert.equal(
execFileSync(tool, ['--version'], { env, encoding: 'utf8', timeout: 10000 }).trim(),
process.argv[3] || '10.9.3',
);
}
}
if (mode === 'system') {
for (const tool of ['npm', 'npx']) {
const args = ['--offline', '--call', 'node --version'];
if (tool === 'npm') args.unshift('exec');
assert.equal(
execFileSync(tool, args, { env, encoding: 'utf8', timeout: 10000 }).trim(),
process.version,
);
}
}
console.log(`Node and its tools survive ${mode} PATH`);
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const assert = require('node:assert/strict');
const { execSync } = require('node:child_process');

assert.equal(process.version, 'v22.18.0');
assert.equal(execSync('npm --version', { encoding: 'utf8' }).trim(), '10.5.0');
console.log('JS delegation preserves the explicit Node and npm versions');
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "vite-plus",
"version": "0.3.1"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "shim-injected-tool-contracts",
"private": true,
"packageManager": "pnpm@10.19.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20.18.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "pnpm-child",
"private": true,
"packageManager": "pnpm@10.19.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
console.log('preload start');
process.on('exit', () => console.log('preload exit'));
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env node
const assert = require('node:assert/strict');
const { execFileSync, execSync } = require('node:child_process');
const path = require('node:path');

assert.equal(process.version, 'v22.18.0');
assert.equal(execFileSync('node', ['--version'], { encoding: 'utf8' }).trim(), process.version);
const shim = path.join(
process.env.VP_HOME,
'bin',
process.platform === 'win32' ? 'node.exe' : 'node',
);
assert.equal(execFileSync(shim, ['--version'], { encoding: 'utf8' }).trim(), process.version);
if (process.argv[2]) {
const npmVersion = execSync('npm --version', { encoding: 'utf8' }).trim();
assert.equal(npmVersion, process.argv[2]);
console.log(`Pinned npm ${npmVersion} is preserved`);
}
console.log('The global package and its Node children use Node 22.18.0');
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "injected-runtime-probe",
"version": "1.0.0",
"bin": {
"injected-runtime-probe": "index.cjs",
"injected-pnpm-probe": "system-pnpm.cjs"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env node
const assert = require('node:assert/strict');
const { execSync } = require('node:child_process');

assert.equal(process.version, 'v22.18.0');
assert.equal(execSync('node --version', { encoding: 'utf8' }).trim(), process.version);
const result = JSON.parse(execSync('pnpm --version', { encoding: 'utf8' }));
assert.equal(result.node, process.version);
const npm = execSync('npm --version', { encoding: 'utf8' }).trim();
assert.equal(result.npm, npm);
if (process.argv[2]) assert.equal(result.npm, process.argv[2]);
console.log('The global package and system pnpm use Node 22.18.0');
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const { mkdirSync, symlinkSync, writeFileSync } = require('node:fs');

mkdirSync('system-npm', { recursive: true });
symlinkSync(process.execPath, 'system-npm/node');
writeFileSync(
'system-npm/npm',
'#!/bin/sh\nif [ "$1" = "--version" ]; then echo 10.5.0; else exec npx --version; fi\n',
{ mode: 0o755 },
);
Loading
Loading