Fix diagnostic serialization crash (#47604)

* Add crashing test

* Fix unsafe cast to DiagnosticMessageChain
This commit is contained in:
Andrew Branch
2022-01-26 10:41:47 -08:00
committed by GitHub
parent 3206df8e6d
commit c191e7c942
4 changed files with 226 additions and 1 deletions

View File

@@ -30121,7 +30121,7 @@ namespace ts {
const diags = max > 1 ? allDiagnostics[minIndex] : flatten(allDiagnostics);
Debug.assert(diags.length > 0, "No errors reported for 3 or fewer overload signatures");
const chain = chainDiagnosticMessages(
map(diags, d => typeof d.messageText === "string" ? (d as DiagnosticMessageChain) : d.messageText),
map(diags, createDiagnosticMessageChainFromDiagnostic),
Diagnostics.No_overload_matches_this_call);
// The below is a spread to guarantee we get a new (mutable) array - our `flatMap` helper tries to do "smart" optimizations where it reuses input
// arrays and the emptyArray singleton where possible, which is decidedly not what we want while we're still constructing this diagnostic

View File

@@ -1071,6 +1071,15 @@ namespace ts {
};
}
export function createDiagnosticMessageChainFromDiagnostic(diagnostic: DiagnosticRelatedInformation): DiagnosticMessageChain {
return typeof diagnostic.messageText === "string" ? {
code: diagnostic.code,
category: diagnostic.category,
messageText: diagnostic.messageText,
next: (diagnostic as DiagnosticMessageChain).next,
} : diagnostic.messageText;
}
export function createDiagnosticForRange(sourceFile: SourceFile, range: TextRange, message: DiagnosticMessage): DiagnosticWithLocation {
return {
file: sourceFile,

View File

@@ -418,5 +418,36 @@ declare global {
incrementalScenarios: noChangeOnlyRuns,
baselinePrograms: true
});
verifyTscSerializedIncrementalEdits({
scenario: "incremental",
subScenario: "serializing error chains",
commandLineArgs: ["-p", `src/project`],
fs: () => loadProjectFromFiles({
"/src/project/tsconfig.json": JSON.stringify({
compilerOptions: {
incremental: true,
strict: true,
jsx: "react",
module: "esnext",
},
}),
"/src/project/index.tsx": Utils.dedent`
declare namespace JSX {
interface ElementChildrenAttribute { children: {}; }
interface IntrinsicElements { div: {} }
}
declare var React: any;
declare function Component(props: never): any;
declare function Component(props: { children?: number }): any;
(<Component>
<div />
<div />
</Component>)`
}, `\ninterface ReadonlyArray<T> { readonly length: number }`),
incrementalScenarios: noChangeOnlyRuns,
});
});
}