Skip to content

Commit 720a3bf

Browse files
author
Andy Hanson
committed
Skip files from package.json "main" or "types" if they have an unsupported extension.
1 parent 0f78f53 commit 720a3bf

12 files changed

+169
-16
lines changed

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2685,6 +2685,10 @@
26852685
"category": "Message",
26862686
"code": 6080
26872687
},
2688+
"File '{0}' has an unsupported extension, so skipping it.": {
2689+
"category": "Message",
2690+
"code": 6081
2691+
},
26882692
"Only 'amd' and 'system' modules are supported alongside --{0}.": {
26892693
"category": "Error",
26902694
"code": 6082

src/compiler/moduleNameResolver.ts

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,6 @@ namespace ts {
4747
return resolved.path;
4848
}
4949

50-
/** Create Resolved from a file with unknown extension. */
51-
function resolvedFromAnyFile(path: string): Resolved | undefined {
52-
return { path, extension: extensionFromPath(path) };
53-
}
54-
5550
/** Adds `isExernalLibraryImport` to a Resolved to get a ResolvedModule. */
5651
function resolvedModuleFromResolved({ path, extension }: Resolved, isExternalLibraryImport: boolean): ResolvedModuleFull {
5752
return { resolvedFileName: path, extension, isExternalLibraryImport };
@@ -71,7 +66,8 @@ namespace ts {
7166
traceEnabled: boolean;
7267
}
7368

74-
function tryReadTypesSection(extensions: Extensions, packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string {
69+
/** Reads from "main" or "types"/"typings" depending on `extensions`. */
70+
function tryReadPackageJsonMainOrTypes(extensions: Extensions, packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string {
7571
const jsonContent = readJson(packageJsonPath, state.host);
7672

7773
switch (extensions) {
@@ -678,18 +674,21 @@ namespace ts {
678674
if (state.traceEnabled) {
679675
trace(state.host, Diagnostics.Found_package_json_at_0, packageJsonPath);
680676
}
681-
const typesFile = tryReadTypesSection(extensions, packageJsonPath, candidate, state);
682-
if (typesFile) {
683-
const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(typesFile), state.host);
677+
const mainOrTypesFile = tryReadPackageJsonMainOrTypes(extensions, packageJsonPath, candidate, state);
678+
if (mainOrTypesFile) {
679+
const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(mainOrTypesFile), state.host);
684680
// A package.json "typings" may specify an exact filename, or may choose to omit an extension.
685-
const fromFile = tryFile(typesFile, failedLookupLocations, onlyRecordFailures, state);
686-
if (fromFile) {
687-
// Note: this would allow a package.json to specify a ".js" file as typings. Maybe that should be forbidden.
688-
return resolvedFromAnyFile(fromFile);
681+
const fromExactFile = tryFile(mainOrTypesFile, failedLookupLocations, onlyRecordFailures, state);
682+
if (fromExactFile) {
683+
const resolved = fromExactFile && resolvedFromSuspiciousFile(extensions, fromExactFile);
684+
if (resolved) {
685+
return resolved;
686+
}
687+
trace(state.host, Diagnostics.File_0_has_an_unsupported_extension_so_skipping_it, fromExactFile);
689688
}
690-
const x = tryAddingExtensions(typesFile, Extensions.TypeScript, failedLookupLocations, onlyRecordFailures, state);
691-
if (x) {
692-
return x;
689+
const resolved = tryAddingExtensions(mainOrTypesFile, Extensions.TypeScript, failedLookupLocations, onlyRecordFailures, state);
690+
if (resolved) {
691+
return resolved;
693692
}
694693
}
695694
else {
@@ -709,6 +708,24 @@ namespace ts {
709708
return loadModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocations, !directoryExists, state);
710709
}
711710

711+
/** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */
712+
function resolvedFromSuspiciousFile(extensions: Extensions, path: string): Resolved | undefined {
713+
const extension = tryGetExtensionFromPath(path);
714+
return extension !== undefined && extensionIsOk(extensions, extension) ? { path, extension } : undefined;
715+
}
716+
717+
/** True if `extension` is one of the supported `extensions`. */
718+
function extensionIsOk(extensions: Extensions, extension: Extension): boolean {
719+
switch (extensions) {
720+
case Extensions.JavaScript:
721+
return extension === Extension.Js || extension === Extension.Jsx;
722+
case Extensions.TypeScript:
723+
return extension === Extension.Ts || extension === Extension.Tsx || extension === Extension.Dts;
724+
case Extensions.DtsOnly:
725+
return extension === Extension.Dts;
726+
}
727+
}
728+
712729
function pathToPackageJson(directory: string): string {
713730
return combinePaths(directory, "package.json");
714731
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//// [tests/cases/compiler/moduleResolutionWithExtensions_unexpected.ts] ////
2+
3+
//// [normalize.css]
4+
// This tests that a package.json "main" with an unexpected extension is ignored.
5+
6+
This file is not read.
7+
8+
//// [package.json]
9+
{ "main": "normalize.css" }
10+
11+
//// [a.ts]
12+
import "normalize.css";
13+
14+
15+
//// [a.js]
16+
"use strict";
17+
require("normalize.css");
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
=== /a.ts ===
2+
import "normalize.css";
3+
No type information for this code.
4+
No type information for this code.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[
2+
"======== Resolving module 'normalize.css' from '/a.ts'. ========",
3+
"Module resolution kind is not specified, using 'NodeJs'.",
4+
"Loading module 'normalize.css' from 'node_modules' folder.",
5+
"File '/node_modules/normalize.css.ts' does not exist.",
6+
"File '/node_modules/normalize.css.tsx' does not exist.",
7+
"File '/node_modules/normalize.css.d.ts' does not exist.",
8+
"Found 'package.json' at '/node_modules/normalize.css/package.json'.",
9+
"'package.json' does not have a 'types' or 'main' field.",
10+
"File '/node_modules/normalize.css/index.ts' does not exist.",
11+
"File '/node_modules/normalize.css/index.tsx' does not exist.",
12+
"File '/node_modules/normalize.css/index.d.ts' does not exist.",
13+
"File '/node_modules/@types/normalize.css.d.ts' does not exist.",
14+
"File '/node_modules/@types/normalize.css/package.json' does not exist.",
15+
"File '/node_modules/@types/normalize.css/index.d.ts' does not exist.",
16+
"Loading module 'normalize.css' from 'node_modules' folder.",
17+
"File '/node_modules/normalize.css.js' does not exist.",
18+
"File '/node_modules/normalize.css.jsx' does not exist.",
19+
"Found 'package.json' at '/node_modules/normalize.css/package.json'.",
20+
"No types specified in 'package.json', so returning 'main' value of 'normalize.css'",
21+
"File '/node_modules/normalize.css/normalize.css' exist - use it as a name resolution result.",
22+
"File '/node_modules/normalize.css/normalize.css' has an unsupported extension, so skipping it.",
23+
"File '/node_modules/normalize.css/normalize.css.ts' does not exist.",
24+
"File '/node_modules/normalize.css/normalize.css.tsx' does not exist.",
25+
"File '/node_modules/normalize.css/normalize.css.d.ts' does not exist.",
26+
"File '/node_modules/normalize.css/index.js' does not exist.",
27+
"File '/node_modules/normalize.css/index.jsx' does not exist.",
28+
"======== Module name 'normalize.css' was not resolved. ========"
29+
]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
=== /a.ts ===
2+
import "normalize.css";
3+
No type information for this code.
4+
No type information for this code.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//// [tests/cases/compiler/moduleResolutionWithExtensions_unexpected2.ts] ////
2+
3+
//// [foo.js]
4+
// This tests that a package.json "types" with an unexpected extension is ignored.
5+
6+
This file is not read.
7+
8+
//// [package.json]
9+
{ "types": "foo.js" }
10+
11+
//// [a.ts]
12+
import "foo";
13+
14+
15+
//// [a.js]
16+
"use strict";
17+
require("foo");
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
=== /a.ts ===
2+
import "foo";
3+
No type information for this code.
4+
No type information for this code.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[
2+
"======== Resolving module 'foo' from '/a.ts'. ========",
3+
"Module resolution kind is not specified, using 'NodeJs'.",
4+
"Loading module 'foo' from 'node_modules' folder.",
5+
"File '/node_modules/foo.ts' does not exist.",
6+
"File '/node_modules/foo.tsx' does not exist.",
7+
"File '/node_modules/foo.d.ts' does not exist.",
8+
"Found 'package.json' at '/node_modules/foo/package.json'.",
9+
"'package.json' has 'types' field 'foo.js' that references '/node_modules/foo/foo.js'.",
10+
"File '/node_modules/foo/foo.js' exist - use it as a name resolution result.",
11+
"File '/node_modules/foo/foo.js' has an unsupported extension, so skipping it.",
12+
"File '/node_modules/foo/foo.js.ts' does not exist.",
13+
"File '/node_modules/foo/foo.js.tsx' does not exist.",
14+
"File '/node_modules/foo/foo.js.d.ts' does not exist.",
15+
"File '/node_modules/foo/index.ts' does not exist.",
16+
"File '/node_modules/foo/index.tsx' does not exist.",
17+
"File '/node_modules/foo/index.d.ts' does not exist.",
18+
"File '/node_modules/@types/foo.d.ts' does not exist.",
19+
"File '/node_modules/@types/foo/package.json' does not exist.",
20+
"File '/node_modules/@types/foo/index.d.ts' does not exist.",
21+
"Loading module 'foo' from 'node_modules' folder.",
22+
"File '/node_modules/foo.js' does not exist.",
23+
"File '/node_modules/foo.jsx' does not exist.",
24+
"Found 'package.json' at '/node_modules/foo/package.json'.",
25+
"'package.json' does not have a 'types' or 'main' field.",
26+
"File '/node_modules/foo/index.js' does not exist.",
27+
"File '/node_modules/foo/index.jsx' does not exist.",
28+
"======== Module name 'foo' was not resolved. ========"
29+
]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
=== /a.ts ===
2+
import "foo";
3+
No type information for this code.
4+
No type information for this code.

0 commit comments

Comments
 (0)