Treat explicit imports from node_modules as external library imports (#16364)

* Treat explicit imports from `node_modules` as external library imports

* Update baselines
This commit is contained in:
Andy 2017-08-17 13:26:38 -07:00 committed by GitHub
parent babb88a0aa
commit eef7d8bd3d
16 changed files with 99 additions and 29 deletions

View file

@ -1694,7 +1694,6 @@ namespace ts {
if (ambientModule) { if (ambientModule) {
return ambientModule; return ambientModule;
} }
const isRelative = isExternalModuleNameRelative(moduleReference);
const resolvedModule = getResolvedModule(getSourceFileOfNode(location), moduleReference); const resolvedModule = getResolvedModule(getSourceFileOfNode(location), moduleReference);
const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule); const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule);
const sourceFile = resolvedModule && !resolutionDiagnostic && host.getSourceFile(resolvedModule.resolvedFileName); const sourceFile = resolvedModule && !resolutionDiagnostic && host.getSourceFile(resolvedModule.resolvedFileName);
@ -1718,7 +1717,7 @@ namespace ts {
} }
// May be an untyped module. If so, ignore resolutionDiagnostic. // May be an untyped module. If so, ignore resolutionDiagnostic.
if (!isRelative && resolvedModule && !extensionIsTypeScript(resolvedModule.extension)) { if (resolvedModule && resolvedModule.isExternalLibraryImport && !extensionIsTypeScript(resolvedModule.extension)) {
if (isForAugmentation) { if (isForAugmentation) {
const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented;
error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName); error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName);

View file

@ -1543,16 +1543,20 @@ namespace ts {
} }
export function normalizePath(path: string): string { export function normalizePath(path: string): string {
return normalizePathAndParts(path).path;
}
export function normalizePathAndParts(path: string): { path: string, parts: string[] } {
path = normalizeSlashes(path); path = normalizeSlashes(path);
const rootLength = getRootLength(path); const rootLength = getRootLength(path);
const root = path.substr(0, rootLength); const root = path.substr(0, rootLength);
const normalized = getNormalizedParts(path, rootLength); const parts = getNormalizedParts(path, rootLength);
if (normalized.length) { if (parts.length) {
const joinedParts = root + normalized.join(directorySeparator); const joinedParts = root + parts.join(directorySeparator);
return pathEndsWithDirectorySeparator(path) ? joinedParts + directorySeparator : joinedParts; return { path: pathEndsWithDirectorySeparator(path) ? joinedParts + directorySeparator : joinedParts, parts };
} }
else { else {
return root; return { path: root, parts };
} }
} }

View file

@ -747,9 +747,10 @@ namespace ts {
return { value: resolvedValue && { resolved: resolvedValue, isExternalLibraryImport: true } }; return { value: resolvedValue && { resolved: resolvedValue, isExternalLibraryImport: true } };
} }
else { else {
const candidate = normalizePath(combinePaths(containingDirectory, moduleName)); const { path: candidate, parts } = normalizePathAndParts(combinePaths(containingDirectory, moduleName));
const resolved = nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true); const resolved = nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true);
return resolved && toSearchResult({ resolved, isExternalLibraryImport: false }); // Treat explicit "node_modules" import as an external library import.
return resolved && toSearchResult({ resolved, isExternalLibraryImport: contains(parts, "node_modules") });
} }
} }
} }

View file

@ -3953,12 +3953,7 @@ namespace ts {
export interface ResolvedModule { export interface ResolvedModule {
/** Path of the file the module was resolved to. */ /** Path of the file the module was resolved to. */
resolvedFileName: string; resolvedFileName: string;
/** /** True if `resolvedFileName` comes from `node_modules`. */
* Denotes if 'resolvedFileName' is isExternalLibraryImport and thus should be a proper external module:
* - be a .d.ts file
* - use top level imports\exports
* - don't use tripleslash references
*/
isExternalLibraryImport?: boolean; isExternalLibraryImport?: boolean;
} }

View file

@ -0,0 +1,12 @@
//// [tests/cases/compiler/moduleResolution_explicitNodeModulesImport.ts] ////
//// [index.js]
exports.x = 0;
//// [index.ts]
import { x } from "../node_modules/foo";
//// [index.js]
"use strict";
exports.__esModule = true;

View file

@ -0,0 +1,9 @@
=== /src/index.ts ===
import { x } from "../node_modules/foo";
>x : Symbol(x, Decl(index.ts, 0, 8))
=== /node_modules/foo/index.js ===
exports.x = 0;
>exports : Symbol(x, Decl(index.js, 0, 0))
>x : Symbol(x, Decl(index.js, 0, 0))

View file

@ -0,0 +1,12 @@
=== /src/index.ts ===
import { x } from "../node_modules/foo";
>x : number
=== /node_modules/foo/index.js ===
exports.x = 0;
>exports.x = 0 : 0
>exports.x : any
>exports : any
>x : any
>0 : 0

View file

@ -0,0 +1,12 @@
//// [tests/cases/compiler/moduleResolution_explicitNodeModulesImport_implicitAny.ts] ////
//// [index.js]
exports.x = 0;
//// [index.ts]
import { y } from "../node_modules/foo";
//// [index.js]
"use strict";
exports.__esModule = true;

View file

@ -0,0 +1,4 @@
=== /src/index.ts ===
import { y } from "../node_modules/foo";
>y : Symbol(y, Decl(index.ts, 0, 8))

View file

@ -0,0 +1,4 @@
=== /src/index.ts ===
import { y } from "../node_modules/foo";
>y : any

View file

@ -13,9 +13,6 @@ maxDepthExceeded/root.ts(4,4): error TS2540: Cannot assign to 'rel' because it i
"exclude": ["node_modules/m2/**/*"] "exclude": ["node_modules/m2/**/*"]
} }
==== relative.js (0 errors) ====
exports.relativeProp = true;
==== index.js (0 errors) ==== ==== index.js (0 errors) ====
var m2 = require('m2'); var m2 = require('m2');
var rel = require('./relative'); var rel = require('./relative');
@ -51,4 +48,7 @@ maxDepthExceeded/root.ts(4,4): error TS2540: Cannot assign to 'rel' because it i
"b": "hello, world", "b": "hello, world",
"person": m3.person "person": m3.person
}; };
==== relative.js (0 errors) ====
exports.relativeProp = true;

View file

@ -7,14 +7,14 @@
"project": "maxDepthExceeded", "project": "maxDepthExceeded",
"resolvedInputFiles": [ "resolvedInputFiles": [
"lib.d.ts", "lib.d.ts",
"maxDepthExceeded/node_modules/m1/relative.js",
"maxDepthExceeded/node_modules/m1/index.js", "maxDepthExceeded/node_modules/m1/index.js",
"maxDepthExceeded/root.ts", "maxDepthExceeded/root.ts",
"maxDepthExceeded/node_modules/m2/entry.js" "maxDepthExceeded/node_modules/m2/entry.js",
"maxDepthExceeded/node_modules/m1/relative.js"
], ],
"emittedFiles": [ "emittedFiles": [
"maxDepthExceeded/built/node_modules/m1/relative.js",
"maxDepthExceeded/built/node_modules/m1/index.js", "maxDepthExceeded/built/node_modules/m1/index.js",
"maxDepthExceeded/built/root.js" "maxDepthExceeded/built/root.js",
"maxDepthExceeded/built/node_modules/m1/relative.js"
] ]
} }

View file

@ -13,9 +13,6 @@ maxDepthExceeded/root.ts(4,4): error TS2540: Cannot assign to 'rel' because it i
"exclude": ["node_modules/m2/**/*"] "exclude": ["node_modules/m2/**/*"]
} }
==== relative.js (0 errors) ====
exports.relativeProp = true;
==== index.js (0 errors) ==== ==== index.js (0 errors) ====
var m2 = require('m2'); var m2 = require('m2');
var rel = require('./relative'); var rel = require('./relative');
@ -51,4 +48,7 @@ maxDepthExceeded/root.ts(4,4): error TS2540: Cannot assign to 'rel' because it i
"b": "hello, world", "b": "hello, world",
"person": m3.person "person": m3.person
}; };
==== relative.js (0 errors) ====
exports.relativeProp = true;

View file

@ -7,14 +7,14 @@
"project": "maxDepthExceeded", "project": "maxDepthExceeded",
"resolvedInputFiles": [ "resolvedInputFiles": [
"lib.d.ts", "lib.d.ts",
"maxDepthExceeded/node_modules/m1/relative.js",
"maxDepthExceeded/node_modules/m1/index.js", "maxDepthExceeded/node_modules/m1/index.js",
"maxDepthExceeded/root.ts", "maxDepthExceeded/root.ts",
"maxDepthExceeded/node_modules/m2/entry.js" "maxDepthExceeded/node_modules/m2/entry.js",
"maxDepthExceeded/node_modules/m1/relative.js"
], ],
"emittedFiles": [ "emittedFiles": [
"maxDepthExceeded/built/node_modules/m1/relative.js",
"maxDepthExceeded/built/node_modules/m1/index.js", "maxDepthExceeded/built/node_modules/m1/index.js",
"maxDepthExceeded/built/root.js" "maxDepthExceeded/built/root.js",
"maxDepthExceeded/built/node_modules/m1/relative.js"
] ]
} }

View file

@ -0,0 +1,9 @@
// @allowJs: true
// @noImplicitReferences: true
// @maxNodeModuleJsDepth: 1
// @Filename: /node_modules/foo/index.js
exports.x = 0;
// @Filename: /src/index.ts
import { x } from "../node_modules/foo";

View file

@ -0,0 +1,9 @@
// @allowJs: true
// @noImplicitReferences: true
// @maxNodeModuleJsDepth: 0
// @Filename: /node_modules/foo/index.js
exports.x = 0;
// @Filename: /src/index.ts
import { y } from "../node_modules/foo";