Skip to content

Commit

Permalink
Merge branch 'main' into fix59252
Browse files Browse the repository at this point in the history
# Conflicts:
#	tests/baselines/reference/typeGuardFunctionOfFormThisErrors.errors.txt
  • Loading branch information
RyanCavanaugh committed Jul 16, 2024
2 parents 1a2fd75 + 0e4a899 commit 8fb70af
Show file tree
Hide file tree
Showing 317 changed files with 10,110 additions and 2,653 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ jobs:
- name: Upload baseline diff artifact
if: ${{ failure() && steps.check-baselines.conclusion == 'failure' }}
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with:
name: fix_baselines.patch
path: fix_baselines.patch
2 changes: 1 addition & 1 deletion .github/workflows/release-branch-artifact.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
npm pack ./
mv typescript-*.tgz typescript.tgz
- name: Upload built tarfile
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with:
name: tgz
path: typescript.tgz
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: 'Upload artifact'
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with:
name: SARIF file
path: results.sarif
Expand Down
18 changes: 12 additions & 6 deletions src/compiler/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
concatenate,
convertToOptionsWithAbsolutePaths,
createGetCanonicalFileName,
createModeMismatchDetails,
createModuleNotFoundChain,
createProgram,
CustomTransformers,
Expand Down Expand Up @@ -70,7 +71,6 @@ import {
ReadBuildProgramHost,
ReadonlyCollection,
RepopulateDiagnosticChainInfo,
RepopulateModuleNotFoundDiagnosticChain,
returnFalse,
returnUndefined,
sameMap,
Expand Down Expand Up @@ -111,8 +111,8 @@ export interface ReusableDiagnosticRelatedInformation {
}

/** @internal */
export interface ReusableRepopulateModuleNotFoundChain {
info: RepopulateModuleNotFoundDiagnosticChain;
export interface ReusableRepopulateInfoChain {
info: RepopulateDiagnosticChainInfo;
next?: ReusableDiagnosticMessageChain[];
}

Expand All @@ -122,7 +122,7 @@ export type SerializedDiagnosticMessageChain = Omit<DiagnosticMessageChain, "nex
};

/** @internal */
export type ReusableDiagnosticMessageChain = SerializedDiagnosticMessageChain | ReusableRepopulateModuleNotFoundChain;
export type ReusableDiagnosticMessageChain = SerializedDiagnosticMessageChain | ReusableRepopulateInfoChain;

/**
* Signature (Hash of d.ts emitted), is string if it was emitted using same d.ts.map option as what compilerOptions indicate, otherwise tuple of string
Expand Down Expand Up @@ -538,7 +538,13 @@ function convertOrRepopulateDiagnosticMessageChain<T extends DiagnosticMessageCh
repopulateInfo: (chain: T) => RepopulateDiagnosticChainInfo | undefined,
): DiagnosticMessageChain {
const info = repopulateInfo(chain);
if (info) {
if (info === true) {
return {
...createModeMismatchDetails(sourceFile!),
next: convertOrRepopulateDiagnosticMessageChainArray(chain.next as T[], sourceFile, newProgram, repopulateInfo),
};
}
else if (info) {
return {
...createModuleNotFoundChain(sourceFile!, newProgram, info.moduleReference, info.mode, info.packageName || info.moduleReference),
next: convertOrRepopulateDiagnosticMessageChainArray(chain.next as T[], sourceFile, newProgram, repopulateInfo),
Expand Down Expand Up @@ -600,7 +606,7 @@ function convertToDiagnosticRelatedInformation(
file: sourceFile,
messageText: isString(diagnostic.messageText) ?
diagnostic.messageText :
convertOrRepopulateDiagnosticMessageChain(diagnostic.messageText, sourceFile, newProgram, chain => (chain as ReusableRepopulateModuleNotFoundChain).info),
convertOrRepopulateDiagnosticMessageChain(diagnostic.messageText, sourceFile, newProgram, chain => (chain as ReusableRepopulateInfoChain).info),
};
}

Expand Down
308 changes: 152 additions & 156 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
type: "boolean",
affectsEmit: true,
affectsBuildInfo: true,
affectsSourceFile: true,
category: Diagnostics.Emit,
description: Diagnostics.Allow_importing_helper_functions_from_tslib_once_per_project_instead_of_including_them_per_file,
defaultValueDescription: false,
Expand Down Expand Up @@ -1265,6 +1266,7 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
affectsEmit: true,
affectsBuildInfo: true,
affectsModuleResolution: true,
affectsSourceFile: true,
category: Diagnostics.Language_and_Environment,
description: Diagnostics.Specify_module_specifier_used_to_import_the_JSX_factory_functions_when_using_jsx_Colon_react_jsx_Asterisk,
defaultValueDescription: "react",
Expand Down
10 changes: 1 addition & 9 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2680,10 +2680,6 @@
"category": "Error",
"code": 2524
},
"Initializer provides no value for this binding element and the binding element has no default value.": {
"category": "Error",
"code": 2525
},
"A 'this' type is available only in a non-static member of a class or interface.": {
"category": "Error",
"code": 2526
Expand Down Expand Up @@ -4212,7 +4208,7 @@
"category": "Error",
"code": 4092
},
"Property '{0}' of exported class expression may not be private or protected.": {
"Property '{0}' of exported anonymous class type may not be private or protected.": {
"category": "Error",
"code": 4094
},
Expand Down Expand Up @@ -5113,10 +5109,6 @@
"category": "Message",
"code": 6144
},
"Module '{0}' was resolved as ambient module declared in '{1}' since this file was not modified.": {
"category": "Message",
"code": 6145
},
"Specify the JSX factory function to use when targeting 'react' JSX emit, e.g. 'React.createElement' or 'h'.": {
"category": "Message",
"code": 6146
Expand Down
20 changes: 7 additions & 13 deletions src/compiler/moduleNameResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2382,17 +2382,11 @@ export interface PackageJsonInfoContents {
*
* @internal
*/
export function getPackageScopeForPath(fileName: string, state: ModuleResolutionState): PackageJsonInfo | undefined {
const parts = getPathComponents(fileName);
parts.pop();
while (parts.length > 0) {
const pkg = getPackageJsonInfo(getPathFromPathComponents(parts), /*onlyRecordFailures*/ false, state);
if (pkg) {
return pkg;
}
parts.pop();
}
return undefined;
export function getPackageScopeForPath(directory: string, state: ModuleResolutionState): PackageJsonInfo | undefined {
return forEachAncestorDirectory(
directory,
dir => getPackageJsonInfo(dir, /*onlyRecordFailures*/ false, state),
);
}

function getVersionPathsOfPackageJsonInfo(packageJsonInfo: PackageJsonInfo, state: ModuleResolutionState): VersionPaths | undefined {
Expand Down Expand Up @@ -2568,7 +2562,7 @@ function noKeyStartsWithDot(obj: MapLike<unknown>) {
}

function loadModuleFromSelfNameReference(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult<Resolved> {
const directoryPath = getNormalizedAbsolutePath(combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.());
const directoryPath = getNormalizedAbsolutePath(directory, state.host.getCurrentDirectory?.());
const scope = getPackageScopeForPath(directoryPath, state);
if (!scope || !scope.contents.packageJsonContent.exports) {
return undefined;
Expand Down Expand Up @@ -2649,7 +2643,7 @@ function loadModuleFromImports(extensions: Extensions, moduleName: string, direc
}
return toSearchResult(/*value*/ undefined);
}
const directoryPath = getNormalizedAbsolutePath(combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.());
const directoryPath = getNormalizedAbsolutePath(directory, state.host.getCurrentDirectory?.());
const scope = getPackageScopeForPath(directoryPath, state);
if (!scope) {
if (state.traceEnabled) {
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/moduleSpecifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@ function getAllModulePathsWorker(info: Info, importedFileName: string, host: Mod
// This should populate all the relevant symlinks in the symlink cache, and most, if not all, of these resolutions
// should get (re)used.
const state = getTemporaryModuleResolutionState(cache.getPackageJsonInfoCache(), host, {});
const packageJson = getPackageScopeForPath(info.importingSourceFileName, state);
const packageJson = getPackageScopeForPath(getDirectoryPath(info.importingSourceFileName), state);
if (packageJson) {
const toResolve = getAllRuntimeDependencies(packageJson.contents.packageJsonContent);
for (const depName of (toResolve || emptyArray)) {
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2637,7 +2637,7 @@ namespace Parser {
function createIdentifier(isIdentifier: boolean, diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier {
if (isIdentifier) {
identifierCount++;
const pos = getNodePos();
const pos = scanner.hasPrecedingJSDocLeadingAsterisks() ? scanner.getTokenStart() : getNodePos();
// Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker
const originalKeywordKind = token();
const text = internIdentifier(scanner.getTokenValue());
Expand Down
13 changes: 8 additions & 5 deletions src/compiler/performanceCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@ function tryGetPerformance() {
if (isNodeLikeSystem()) {
try {
// By default, only write native events when generating a cpu profile or using the v8 profiler.
const { performance } = require("perf_hooks") as typeof import("perf_hooks");
return {
shouldWriteNativeEvents: false,
performance,
};
// Some environments may polyfill this module with an empty object; verify the object has the expected shape.
const { performance } = require("perf_hooks") as Partial<typeof import("perf_hooks")>;
if (performance) {
return {
shouldWriteNativeEvents: false,
performance,
};
}
}
catch {
// ignore errors
Expand Down
85 changes: 25 additions & 60 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1363,7 +1363,7 @@ export function getImpliedNodeFormatForFileWorker(
const packageJsonLocations: string[] = [];
state.failedLookupLocations = packageJsonLocations;
state.affectingLocations = packageJsonLocations;
const packageJsonScope = getPackageScopeForPath(fileName, state);
const packageJsonScope = getPackageScopeForPath(getDirectoryPath(fileName), state);
const impliedNodeFormat = packageJsonScope?.contents.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS;
return { impliedNodeFormat, packageJsonLocations, packageJsonScope };
}
Expand Down Expand Up @@ -1545,7 +1545,6 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
let commonSourceDirectory: string;
let typeChecker: TypeChecker;
let classifiableNames: Set<__String>;
const ambientModuleNameToUnmodifiedFileName = new Map<string, string>();
let fileReasons = createMultiMap<Path, FileIncludeReason>();
let filesWithReferencesProcessed: Set<Path> | undefined;
let fileReasonsToChain: Map<Path, FileReasonToChainCache> | undefined;
Expand Down Expand Up @@ -2250,52 +2249,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
canReuseResolutionsInFile: () =>
containingFile === oldProgram?.getSourceFile(containingFile.fileName) &&
!hasInvalidatedResolutions(containingFile.path),
isEntryResolvingToAmbientModule: moduleNameResolvesToAmbientModule,
resolveToOwnAmbientModule: true,
});
}

function moduleNameResolvesToAmbientModule(moduleName: StringLiteralLike, file: SourceFile) {
// We know moduleName resolves to an ambient module provided that moduleName:
// - is in the list of ambient modules locally declared in the current source file.
// - resolved to an ambient module in the old program whose declaration is in an unmodified file
// (so the same module declaration will land in the new program)
if (contains(file.ambientModuleNames, moduleName.text)) {
if (isTraceEnabled(options, host)) {
trace(host, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName.text, getNormalizedAbsolutePath(file.originalFileName, currentDirectory));
}
return true;
}
else {
return moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName, file);
}
}

// If we change our policy of rechecking failed lookups on each program create,
// we should adjust the value returned here.
function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: StringLiteralLike, file: SourceFile): boolean {
const resolutionToFile = oldProgram?.getResolvedModule(file, moduleName.text, getModeForUsageLocation(file, moduleName))?.resolvedModule;
const resolvedFile = resolutionToFile && oldProgram!.getSourceFile(resolutionToFile.resolvedFileName);
if (resolutionToFile && resolvedFile) {
// In the old program, we resolved to an ambient module that was in the same
// place as we expected to find an actual module file.
// We actually need to return 'false' here even though this seems like a 'true' case
// because the normal module resolution algorithm will find this anyway.
return false;
}

// at least one of declarations should come from non-modified source file
const unmodifiedFile = ambientModuleNameToUnmodifiedFileName.get(moduleName.text);

if (!unmodifiedFile) {
return false;
}

if (isTraceEnabled(options, host)) {
trace(host, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName.text, unmodifiedFile);
}
return true;
}

function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly FileReference[], containingFile: SourceFile): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly string[], containingFile: string): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
function resolveTypeReferenceDirectiveNamesReusingOldState<T extends string | FileReference>(typeDirectiveNames: readonly T[], containingFile: string | SourceFile): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] {
Expand Down Expand Up @@ -2333,7 +2290,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
getResolutionFromOldProgram: (name: string, mode: ResolutionMode) => Resolution | undefined;
getResolved: (oldResolution: Resolution) => ResolutionWithResolvedFileName | undefined;
canReuseResolutionsInFile: () => boolean;
isEntryResolvingToAmbientModule?: (entry: Entry, containingFile: SourceFileOrString) => boolean;
resolveToOwnAmbientModule?: true;
}

function resolveNamesReusingOldState<Entry, SourceFileOrString, SourceFileOrUndefined extends SourceFile | undefined, Resolution>({
Expand All @@ -2346,10 +2303,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
getResolutionFromOldProgram,
getResolved,
canReuseResolutionsInFile,
isEntryResolvingToAmbientModule,
resolveToOwnAmbientModule,
}: ResolveNamesReusingOldStateInput<Entry, SourceFileOrString, SourceFileOrUndefined, Resolution>): readonly Resolution[] {
if (!entries.length) return emptyArray;
if (structureIsReused === StructureIsReused.Not && (!isEntryResolvingToAmbientModule || !containingSourceFile!.ambientModuleNames.length)) {
if (structureIsReused === StructureIsReused.Not && (!resolveToOwnAmbientModule || !containingSourceFile!.ambientModuleNames.length)) {
// If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules,
// the best we can do is fallback to the default logic.
return resolutionWorker(
Expand Down Expand Up @@ -2394,14 +2351,27 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
continue;
}
}
if (isEntryResolvingToAmbientModule?.(entry, containingFile)) {
(result ??= new Array(entries.length))[i] = emptyResolution;
}
else {
// Resolution failed in the old program, or resolved to an ambient module for which we can't reuse the result.
(unknownEntries ??= []).push(entry);
(unknownEntryIndices ??= []).push(i);
if (resolveToOwnAmbientModule) {
const name = nameAndModeGetter.getName(entry);
// We know moduleName resolves to an ambient module provided that moduleName:
// - is in the list of ambient modules locally declared in the current source file.
if (contains(containingSourceFile!.ambientModuleNames, name)) {
if (isTraceEnabled(options, host)) {
trace(
host,
Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1,
name,
getNormalizedAbsolutePath(containingSourceFile!.originalFileName, currentDirectory),
);
}
(result ??= new Array(entries.length))[i] = emptyResolution;
continue;
}
}

// Resolution failed in the old program, or resolved to an ambient module for which we can't reuse the result.
(unknownEntries ??= []).push(entry);
(unknownEntryIndices ??= []).push(i);
}

if (!unknownEntries) return result!;
Expand Down Expand Up @@ -2586,11 +2556,6 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
// add file to the modified list so that we will resolve it later
modifiedSourceFiles.push(newSourceFile);
}
else {
for (const moduleName of oldSourceFile.ambientModuleNames) {
ambientModuleNameToUnmodifiedFileName.set(moduleName, oldSourceFile.fileName);
}
}

// if file has passed all checks it should be safe to reuse it
newSourceFiles.push(newSourceFile);
Expand Down
Loading

0 comments on commit 8fb70af

Please sign in to comment.