Skip to content

Commit 4828c7a

Browse files
authored
Lower RWC Harness Memory Overhead (microsoft#17692)
* Allow original compilation to be freed before checking declarations * Use string concatenation in error baseline * Fix lints * No ternary
1 parent 9be0f1b commit 4828c7a

File tree

2 files changed

+53
-23
lines changed

2 files changed

+53
-23
lines changed

src/harness/harness.ts

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,13 +1194,21 @@ namespace Harness {
11941194
return { result, options };
11951195
}
11961196

1197-
export function compileDeclarationFiles(inputFiles: TestFile[],
1197+
export interface DeclarationCompilationContext {
1198+
declInputFiles: TestFile[];
1199+
declOtherFiles: TestFile[];
1200+
harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions;
1201+
options: ts.CompilerOptions;
1202+
currentDirectory: string;
1203+
}
1204+
1205+
export function prepareDeclarationCompilationContext(inputFiles: TestFile[],
11981206
otherFiles: TestFile[],
11991207
result: CompilerResult,
12001208
harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions,
12011209
options: ts.CompilerOptions,
12021210
// Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
1203-
currentDirectory: string) {
1211+
currentDirectory: string): DeclarationCompilationContext | undefined {
12041212
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) {
12051213
throw new Error("There were no errors and declFiles generated did not match number of js files generated");
12061214
}
@@ -1212,8 +1220,7 @@ namespace Harness {
12121220
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) {
12131221
ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles));
12141222
ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles));
1215-
const output = compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory || harnessSettings["currentDirectory"]);
1216-
return { declInputFiles, declOtherFiles, declResult: output.result };
1223+
return { declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory: currentDirectory || harnessSettings["currentDirectory"] };
12171224
}
12181225

12191226
function addDtsFile(file: TestFile, dtsFiles: TestFile[]) {
@@ -1259,6 +1266,15 @@ namespace Harness {
12591266
}
12601267
}
12611268

1269+
export function compileDeclarationFiles(context: DeclarationCompilationContext | undefined) {
1270+
if (!context) {
1271+
return;
1272+
}
1273+
const { declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory } = context;
1274+
const output = compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory);
1275+
return { declInputFiles, declOtherFiles, declResult: output.result };
1276+
}
1277+
12621278
function normalizeLineEndings(text: string, lineEnding: string): string {
12631279
let normalized = text.replace(/\r\n?/g, "\n");
12641280
if (lineEnding !== "\n") {
@@ -1273,10 +1289,19 @@ namespace Harness {
12731289

12741290
export function getErrorBaseline(inputFiles: TestFile[], diagnostics: ts.Diagnostic[]) {
12751291
diagnostics.sort(ts.compareDiagnostics);
1276-
const outputLines: string[] = [];
1292+
let outputLines = "";
12771293
// Count up all errors that were found in files other than lib.d.ts so we don't miss any
12781294
let totalErrorsReportedInNonLibraryFiles = 0;
12791295

1296+
let firstLine = true;
1297+
function newLine() {
1298+
if (firstLine) {
1299+
firstLine = false;
1300+
return "";
1301+
}
1302+
return "\r\n";
1303+
}
1304+
12801305
function outputErrorText(error: ts.Diagnostic) {
12811306
const message = ts.flattenDiagnosticMessageText(error.messageText, Harness.IO.newLine());
12821307

@@ -1285,7 +1310,7 @@ namespace Harness {
12851310
.map(s => s.length > 0 && s.charAt(s.length - 1) === "\r" ? s.substr(0, s.length - 1) : s)
12861311
.filter(s => s.length > 0)
12871312
.map(s => "!!! " + ts.DiagnosticCategory[error.category].toLowerCase() + " TS" + error.code + ": " + s);
1288-
errLines.forEach(e => outputLines.push(e));
1313+
errLines.forEach(e => outputLines += (newLine() + e));
12891314

12901315
// do not count errors from lib.d.ts here, they are computed separately as numLibraryDiagnostics
12911316
// if lib.d.ts is explicitly included in input files and there are some errors in it (i.e. because of duplicate identifiers)
@@ -1311,7 +1336,7 @@ namespace Harness {
13111336

13121337

13131338
// Header
1314-
outputLines.push("==== " + inputFile.unitName + " (" + fileErrors.length + " errors) ====");
1339+
outputLines += (newLine() + "==== " + inputFile.unitName + " (" + fileErrors.length + " errors) ====");
13151340

13161341
// Make sure we emit something for every error
13171342
let markedErrorCount = 0;
@@ -1340,7 +1365,7 @@ namespace Harness {
13401365
nextLineStart = lineStarts[lineIndex + 1];
13411366
}
13421367
// Emit this line from the original file
1343-
outputLines.push(" " + line);
1368+
outputLines += (newLine() + " " + line);
13441369
fileErrors.forEach(err => {
13451370
// Does any error start or continue on to this line? Emit squiggles
13461371
const end = ts.textSpanEnd(err);
@@ -1352,7 +1377,7 @@ namespace Harness {
13521377
// Calculate the start of the squiggle
13531378
const squiggleStart = Math.max(0, relativeOffset);
13541379
// TODO/REVIEW: this doesn't work quite right in the browser if a multi file test has files whose names are just the right length relative to one another
1355-
outputLines.push(" " + line.substr(0, squiggleStart).replace(/[^\s]/g, " ") + new Array(Math.min(length, line.length - squiggleStart) + 1).join("~"));
1380+
outputLines += (newLine() + " " + line.substr(0, squiggleStart).replace(/[^\s]/g, " ") + new Array(Math.min(length, line.length - squiggleStart) + 1).join("~"));
13561381

13571382
// If the error ended here, or we're at the end of the file, emit its message
13581383
if ((lineIndex === lines.length - 1) || nextLineStart > end) {
@@ -1383,7 +1408,7 @@ namespace Harness {
13831408
assert.equal(totalErrorsReportedInNonLibraryFiles + numLibraryDiagnostics + numTest262HarnessDiagnostics, diagnostics.length, "total number of errors");
13841409

13851410
return minimalDiagnosticsToString(diagnostics) +
1386-
Harness.IO.newLine() + Harness.IO.newLine() + outputLines.join("\r\n");
1411+
Harness.IO.newLine() + Harness.IO.newLine() + outputLines;
13871412
}
13881413

13891414
export function doErrorBaseline(baselinePath: string, inputFiles: TestFile[], errors: ts.Diagnostic[]) {
@@ -1586,9 +1611,10 @@ namespace Harness {
15861611
}
15871612
}
15881613

1589-
const declFileCompilationResult =
1590-
Harness.Compiler.compileDeclarationFiles(
1591-
toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined);
1614+
const declFileContext = Harness.Compiler.prepareDeclarationCompilationContext(
1615+
toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined
1616+
);
1617+
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(declFileContext);
15921618

15931619
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
15941620
jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n";

src/harness/rwcRunner.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,14 @@ namespace RWC {
208208
}, baselineOpts);
209209
});
210210

211+
it("has the expected types", () => {
212+
// We don't need to pass the extension here because "doTypeAndSymbolBaseline" will append appropriate extension of ".types" or ".symbols"
213+
Harness.Compiler.doTypeAndSymbolBaseline(baseName, compilerResult, inputFiles
214+
.concat(otherFiles)
215+
.filter(file => !!compilerResult.program.getSourceFile(file.unitName))
216+
.filter(e => !Harness.isDefaultLibraryFile(e.unitName)), baselineOpts);
217+
});
218+
211219
// Ideally, a generated declaration file will have no errors. But we allow generated
212220
// declaration file errors as part of the baseline.
213221
it("has the expected errors in generated declaration files", () => {
@@ -217,23 +225,19 @@ namespace RWC {
217225
return null;
218226
}
219227

220-
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(
221-
inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory);
228+
const declContext = Harness.Compiler.prepareDeclarationCompilationContext(
229+
inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory
230+
);
231+
// Reset compilerResult before calling into `compileDeclarationFiles` so the memory from the original compilation can be freed
232+
compilerResult = undefined;
233+
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(declContext);
222234

223235
return Harness.Compiler.minimalDiagnosticsToString(declFileCompilationResult.declResult.errors) +
224236
Harness.IO.newLine() + Harness.IO.newLine() +
225237
Harness.Compiler.getErrorBaseline(tsconfigFiles.concat(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
226238
}, baselineOpts);
227239
}
228240
});
229-
230-
it("has the expected types", () => {
231-
// We don't need to pass the extension here because "doTypeAndSymbolBaseline" will append appropriate extension of ".types" or ".symbols"
232-
Harness.Compiler.doTypeAndSymbolBaseline(baseName, compilerResult, inputFiles
233-
.concat(otherFiles)
234-
.filter(file => !!compilerResult.program.getSourceFile(file.unitName))
235-
.filter(e => !Harness.isDefaultLibraryFile(e.unitName)), baselineOpts);
236-
});
237241
});
238242
}
239243
}

0 commit comments

Comments
 (0)