Skip to content

Commit

Permalink
fix: cater for change in resolveTypeReferenceDirective API in TypeScr…
Browse files Browse the repository at this point in the history
…ipt 4.7 (#1422)

* speculative

* v9.2.7

* node 16
  • Loading branch information
johnnyreilly committed Mar 1, 2022
1 parent dcec071 commit f09024d
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 42 deletions.
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

0 comments on commit f09024d

Please sign in to comment.