Skip to content

Commit 4718ff8

Browse files
authored
Merge pull request #30110 from Microsoft/revertExecFileSync
Revert execFileSync
2 parents e8e7e88 + fd10c12 commit 4718ff8

File tree

3 files changed

+23
-26
lines changed

3 files changed

+23
-26
lines changed

src/testRunner/unittests/tsserver/typingsInstaller.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,19 +1684,19 @@ namespace ts.projectSystem {
16841684
TI.getNpmCommandForInstallation(npmPath, tsVersion, packageNames, packageNames.length - Math.ceil(packageNames.length / 2)).command
16851685
];
16861686
it("works when the command is too long to install all packages at once", () => {
1687-
const commands: [string, string[]][] = [];
1688-
const hasError = TI.installNpmPackages(npmPath, tsVersion, packageNames, (file, args) => {
1689-
commands.push([file, args]);
1687+
const commands: string[] = [];
1688+
const hasError = TI.installNpmPackages(npmPath, tsVersion, packageNames, command => {
1689+
commands.push(command);
16901690
return false;
16911691
});
16921692
assert.isFalse(hasError);
16931693
assert.deepEqual(commands, expectedCommands, "commands");
16941694
});
16951695

16961696
it("installs remaining packages when one of the partial command fails", () => {
1697-
const commands: [string, string[]][] = [];
1698-
const hasError = TI.installNpmPackages(npmPath, tsVersion, packageNames, (file, args) => {
1699-
commands.push([file, args]);
1697+
const commands: string[] = [];
1698+
const hasError = TI.installNpmPackages(npmPath, tsVersion, packageNames, command => {
1699+
commands.push(command);
17001700
return commands.length === 1;
17011701
});
17021702
assert.isTrue(hasError);

src/typingsInstaller/nodeTypingsInstaller.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ namespace ts.server.typingsInstaller {
7070
cwd: string;
7171
encoding: "utf-8";
7272
}
73-
type ExecFileSync = (file: string, args: string[], options: ExecSyncOptions) => string;
73+
type ExecSync = (command: string, options: ExecSyncOptions) => string;
7474

7575
export class NodeTypingsInstaller extends TypingsInstaller {
76-
private readonly nodeExecFileSync: ExecFileSync;
76+
private readonly nodeExecSync: ExecSync;
7777
private readonly npmPath: string;
7878
readonly typesRegistry: Map<MapLike<string>>;
7979

@@ -89,19 +89,23 @@ namespace ts.server.typingsInstaller {
8989
log);
9090
this.npmPath = npmLocation !== undefined ? npmLocation : getDefaultNPMLocation(process.argv[0]);
9191

92+
// If the NPM path contains spaces and isn't wrapped in quotes, do so.
93+
if (stringContains(this.npmPath, " ") && this.npmPath[0] !== `"`) {
94+
this.npmPath = `"${this.npmPath}"`;
95+
}
9296
if (this.log.isEnabled()) {
9397
this.log.writeLine(`Process id: ${process.pid}`);
9498
this.log.writeLine(`NPM location: ${this.npmPath} (explicit '${Arguments.NpmLocation}' ${npmLocation === undefined ? "not " : ""} provided)`);
9599
}
96-
({ execFileSync: this.nodeExecFileSync } = require("child_process"));
100+
({ execSync: this.nodeExecSync } = require("child_process"));
97101

98102
this.ensurePackageDirectoryExists(globalTypingsCacheLocation);
99103

100104
try {
101105
if (this.log.isEnabled()) {
102106
this.log.writeLine(`Updating ${typesRegistryPackageName} npm package...`);
103107
}
104-
this.execFileSyncAndLog(this.npmPath, ["install", "--ignore-scripts", `${typesRegistryPackageName}@${this.latestDistTag}`], { cwd: globalTypingsCacheLocation });
108+
this.execSyncAndLog(`${this.npmPath} install --ignore-scripts ${typesRegistryPackageName}@${this.latestDistTag}`, { cwd: globalTypingsCacheLocation });
105109
if (this.log.isEnabled()) {
106110
this.log.writeLine(`Updated ${typesRegistryPackageName} npm package`);
107111
}
@@ -185,20 +189,20 @@ namespace ts.server.typingsInstaller {
185189
this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(packageNames)}'.`);
186190
}
187191
const start = Date.now();
188-
const hasError = installNpmPackages(this.npmPath, version, packageNames, (file, args) => this.execFileSyncAndLog(file, args, { cwd }));
192+
const hasError = installNpmPackages(this.npmPath, version, packageNames, command => this.execSyncAndLog(command, { cwd }));
189193
if (this.log.isEnabled()) {
190194
this.log.writeLine(`npm install #${requestId} took: ${Date.now() - start} ms`);
191195
}
192196
onRequestCompleted(!hasError);
193197
}
194198

195199
/** Returns 'true' in case of error. */
196-
private execFileSyncAndLog(file: string, args: string[], options: Pick<ExecSyncOptions, "cwd">): boolean {
200+
private execSyncAndLog(command: string, options: Pick<ExecSyncOptions, "cwd">): boolean {
197201
if (this.log.isEnabled()) {
198-
this.log.writeLine(`Exec: ${file} ${args.join(" ")}`);
202+
this.log.writeLine(`Exec: ${command}`);
199203
}
200204
try {
201-
const stdout = this.nodeExecFileSync(file, args, { ...options, encoding: "utf-8" });
205+
const stdout = this.nodeExecSync(command, { ...options, encoding: "utf-8" });
202206
if (this.log.isEnabled()) {
203207
this.log.writeLine(` Succeeded. stdout:${indent(sys.newLine, stdout)}`);
204208
}

src/typingsInstallerCore/typingsInstaller.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,35 +31,28 @@ namespace ts.server.typingsInstaller {
3131
}
3232

3333
/*@internal*/
34-
export function installNpmPackages(npmPath: string, tsVersion: string, packageNames: string[], install: (file: string, args: string[]) => boolean) {
34+
export function installNpmPackages(npmPath: string, tsVersion: string, packageNames: string[], install: (command: string) => boolean) {
3535
let hasError = false;
3636
for (let remaining = packageNames.length; remaining > 0;) {
3737
const result = getNpmCommandForInstallation(npmPath, tsVersion, packageNames, remaining);
3838
remaining = result.remaining;
39-
hasError = install(result.command[0], result.command[1]) || hasError;
39+
hasError = install(result.command) || hasError;
4040
}
4141
return hasError;
4242
}
4343

44-
function getUserAgent(tsVersion: string) {
45-
return `--user-agent="typesInstaller/${tsVersion}"`;
46-
}
47-
const npmInstall = "install", ignoreScripts = "--ignore-scripts", saveDev = "--save-dev";
48-
const commandBaseLength = npmInstall.length + ignoreScripts.length + saveDev.length + getUserAgent("").length + 5;
4944
/*@internal*/
5045
export function getNpmCommandForInstallation(npmPath: string, tsVersion: string, packageNames: string[], remaining: number) {
5146
const sliceStart = packageNames.length - remaining;
52-
let packages: string[], toSlice = remaining;
47+
let command: string, toSlice = remaining;
5348
while (true) {
54-
packages = toSlice === packageNames.length ? packageNames : packageNames.slice(sliceStart, sliceStart + toSlice);
55-
const commandLength = npmPath.length + commandBaseLength + packages.join(" ").length + tsVersion.length;
56-
if (commandLength < 8000) {
49+
command = `${npmPath} install --ignore-scripts ${(toSlice === packageNames.length ? packageNames : packageNames.slice(sliceStart, sliceStart + toSlice)).join(" ")} --save-dev --user-agent="typesInstaller/${tsVersion}"`;
50+
if (command.length < 8000) {
5751
break;
5852
}
5953

6054
toSlice = toSlice - Math.floor(toSlice / 2);
6155
}
62-
const command: [string, string[]] = [npmPath, [npmInstall, ignoreScripts, ...packages, saveDev, getUserAgent(tsVersion)]];
6356
return { command, remaining: remaining - toSlice };
6457
}
6558

0 commit comments

Comments
 (0)