Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cater for change in resolveTypeReferenceDirective API in TypeScript 4.7 #1422

Merged
merged 3 commits into from Mar 1, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/push.yml
Expand Up @@ -48,7 +48,7 @@ jobs:
name: Execution Tests Ubuntu
strategy:
matrix:
node: [12, 14]
node: [14, 16]
ts: [3.8.3, 3.9.3, 4.0.3, 4.1.5, 4.2.4, 4.3.2, 4.4.2, 4.5.2, next]
runs-on: ubuntu-latest
steps:
Expand All @@ -75,7 +75,7 @@ jobs:
name: Execution Tests Windows
strategy:
matrix:
node: [12, 14]
node: [14, 16]
ts: [3.8.3, 3.9.3, 4.0.3, 4.1.5, 4.2.4, 4.3.2, 4.4.2, 4.5.2, next]
runs-on: windows-latest
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Expand Up @@ -13,7 +13,7 @@ jobs:
- name: install node
uses: actions/setup-node@v1
with:
node-version: 14
node-version: 16
registry-url: https://registry.npmjs.org/

- name: install
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog

## v9.2.7

* [cater for change in resolveTypeReferenceDirective API in TypeScript 4.7](https://github.com/TypeStrong/ts-loader/pull/1422) [#1421] - thanks @johnny_reilly and @cspotcode for inspiration in ts-node work here: https://github.com/TypeStrong/ts-node/pull/1648

## v9.2.6

* [Docs fix for thread-loader / history](https://github.com/TypeStrong/ts-loader/pull/1377) - thanks @johnnyreilly

## v9.2.5

* [Add function to get the latest program](https://github.com/TypeStrong/ts-loader/pull/1352) - thanks @Zn4rK
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "ts-loader",
"version": "9.2.6",
"version": "9.2.7",
"description": "TypeScript loader for webpack",
"main": "index.js",
"types": "dist",
Expand Down
25 changes: 25 additions & 0 deletions src/interfaces.ts
Expand Up @@ -307,4 +307,29 @@ export interface ResolvedModule {
isExternalLibraryImport?: boolean;
}

export interface TSCommon {
// Changed in TS 4.7
resolveTypeReferenceDirective(
typeReferenceDirectiveName: string,
containingFile: string | undefined,
options: typescript.CompilerOptions,
host: typescript.ModuleResolutionHost,
redirectedReference?: typescript.ResolvedProjectReference,
cache?: typescript.TypeReferenceDirectiveResolutionCache,
resolutionMode?: typescript.SourceFile['impliedNodeFormat']
): typescript.ResolvedTypeReferenceDirectiveWithFailedLookupLocations;
}

/**
* Compiler APIs we use that are marked internal and not included in TypeScript's public API declarations
* @internal
*/
export interface TSInternal {
// Added in TS 4.7
getModeForFileReference?: (
ref: typescript.FileReference | string,
containingFileMode: typescript.SourceFile['impliedNodeFormat']
) => typescript.SourceFile['impliedNodeFormat'];
}

export type Severity = 'error' | 'warning';
104 changes: 66 additions & 38 deletions src/servicesHost.ts
Expand Up @@ -17,7 +17,9 @@ import {
ServiceHostWhichMayBeCacheable,
SolutionBuilderWithWatchHost,
SolutionDiagnostics,
TSCommon,
TSInstance,
TSInternal,
WatchCallbacks,
WatchFactory,
WatchHost,
Expand Down Expand Up @@ -175,9 +177,10 @@ export function makeServicesHost(
return file.version.toString();
}

const outputFileAndKey = instance.solutionBuilderHost?.getOutputFileAndKeyFromReferencedProject(
fileName
);
const outputFileAndKey =
instance.solutionBuilderHost?.getOutputFileAndKeyFromReferencedProject(
fileName
);
if (outputFileAndKey !== undefined) {
instance.solutionBuilderHost!.outputAffectingInstanceVersion.set(
outputFileAndKey.key,
Expand All @@ -198,9 +201,10 @@ export function makeServicesHost(

if (file === undefined) {
if (instance.solutionBuilderHost) {
const outputFileAndKey = instance.solutionBuilderHost.getOutputFileTextAndKeyFromReferencedProject(
fileName
);
const outputFileAndKey =
instance.solutionBuilderHost.getOutputFileTextAndKeyFromReferencedProject(
fileName
);
if (outputFileAndKey !== undefined) {
instance.solutionBuilderHost!.outputAffectingInstanceVersion.set(
outputFileAndKey.key,
Expand Down Expand Up @@ -288,16 +292,20 @@ function makeResolvers<T extends typescript.ModuleResolutionHost>(
);

const resolveTypeReferenceDirectives = (
typeDirectiveNames: string[],
typeDirectiveNames: string[] | readonly typescript.FileReference[],
containingFile: string,
redirectedReference?: typescript.ResolvedProjectReference
redirectedReference: typescript.ResolvedProjectReference | undefined,
options: typescript.CompilerOptions,
containingFileMode?: typescript.SourceFile['impliedNodeFormat'] | undefined // new impliedNodeFormat is accepted by compilerHost
): (typescript.ResolvedTypeReferenceDirective | undefined)[] =>
typeDirectiveNames.map(
directive =>
resolveTypeReferenceDirective(
directive,
containingFile,
redirectedReference
options,
redirectedReference,
containingFileMode
).resolvedTypeReferenceDirective
);

Expand All @@ -312,9 +320,12 @@ function createWatchFactory(
filePathKeyMapper: (fileName: string) => FilePathKey,
compiler: typeof typescript
): WatchFactory {
const watchedFiles: WatchCallbacks<typescript.FileWatcherCallback> = new Map();
const watchedDirectories: WatchCallbacks<typescript.DirectoryWatcherCallback> = new Map();
const watchedDirectoriesRecursive: WatchCallbacks<typescript.DirectoryWatcherCallback> = new Map();
const watchedFiles: WatchCallbacks<typescript.FileWatcherCallback> =
new Map();
const watchedDirectories: WatchCallbacks<typescript.DirectoryWatcherCallback> =
new Map();
const watchedDirectoriesRecursive: WatchCallbacks<typescript.DirectoryWatcherCallback> =
new Map();

return {
watchedFiles,
Expand Down Expand Up @@ -473,13 +484,8 @@ export function makeWatchHost(
instance: TSInstance,
projectReferences?: ReadonlyArray<typescript.ProjectReference>
) {
const {
compiler,
compilerOptions,
files,
otherFiles,
filePathKeyMapper,
} = instance;
const { compiler, compilerOptions, files, otherFiles, filePathKeyMapper } =
instance;

const { watchFile, watchDirectory, invokeFileWatcher } = createWatchFactory(
filePathKeyMapper,
Expand Down Expand Up @@ -507,9 +513,10 @@ export function makeWatchHost(
readFile: readFileWithCachingText,

watchFile: (fileName, callback, pollingInterval, options) => {
const outputFileKey = instance.solutionBuilderHost?.getOutputFileKeyFromReferencedProject(
fileName
);
const outputFileKey =
instance.solutionBuilderHost?.getOutputFileKeyFromReferencedProject(
fileName
);
if (!outputFileKey || outputFileKey === filePathKeyMapper(fileName)) {
return watchFile(fileName, callback, pollingInterval, options);
}
Expand Down Expand Up @@ -1155,9 +1162,11 @@ export function getSolutionErrors(instance: TSInstance, context: string) {
}

type ResolveTypeReferenceDirective = (
directive: string,
directive: string | typescript.FileReference,
containingFile: string,
redirectedReference?: typescript.ResolvedProjectReference
options: typescript.CompilerOptions,
redirectedReference?: typescript.ResolvedProjectReference,
containingFileMode?: typescript.SourceFile['impliedNodeFormat'] | undefined // new impliedNodeFormat is accepted by compilerHost
) => typescript.ResolvedTypeReferenceDirectiveWithFailedLookupLocations;

function makeResolveTypeReferenceDirective(
Expand All @@ -1172,31 +1181,50 @@ function makeResolveTypeReferenceDirective(
if (customResolveTypeReferenceDirective === undefined) {
// Until the api is published
if (
(compiler as any).createTypeReferenceDirectiveResolutionCache &&
compiler.createTypeReferenceDirectiveResolutionCache !== undefined &&
!instance.typeReferenceResolutionCache
) {
instance.typeReferenceResolutionCache = (compiler as any).createTypeReferenceDirectiveResolutionCache(
moduleResolutionHost.getCurrentDirectory!(),
createGetCanonicalFileName(instance),
instance.compilerOptions,
instance.moduleResolutionCache?.getPackageJsonInfoCache?.()
);
instance.typeReferenceResolutionCache =
compiler.createTypeReferenceDirectiveResolutionCache(
moduleResolutionHost.getCurrentDirectory!(),
createGetCanonicalFileName(instance),
instance.compilerOptions,
instance.moduleResolutionCache?.getPackageJsonInfoCache?.()
);
}
return (directive, containingFile, redirectedReference) =>
// Until the api is published
(compiler.resolveTypeReferenceDirective as any)(
directive,
return (
typeDirectiveName,
containingFile,
options,
redirectedReference,
containingFileMode
) => {
// Copy-pasted from https://github.com/TypeStrong/ts-node/blob/9f789d0d91c6eba30ac7f7aad45194a23b44f159/src/resolver-functions.ts#L139
const nameIsString = typeof typeDirectiveName === 'string';
const mode = nameIsString
? undefined
: (compiler as any as TSInternal).getModeForFileReference!(
typeDirectiveName,
containingFileMode
);
const strName = nameIsString
? typeDirectiveName
: typeDirectiveName.fileName.toLowerCase();
return (compiler as any as TSCommon).resolveTypeReferenceDirective(
strName,
containingFile,
compilerOptions,
options,
moduleResolutionHost,
redirectedReference,
instance.typeReferenceResolutionCache
undefined,
mode
);
};
}

return (directive, containingFile) =>
customResolveTypeReferenceDirective(
directive,
directive as string, // unsure whether we should evolve this further
containingFile,
compilerOptions,
moduleResolutionHost,
Expand Down