mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
JS: Implement import resolution
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.internal.CachedStages
|
||||
private import semmle.javascript.internal.paths.PathExprResolver
|
||||
|
||||
/**
|
||||
* An ECMAScript 2015 module.
|
||||
@@ -725,22 +726,7 @@ abstract class ReExportDeclaration extends ExportDeclaration {
|
||||
cached
|
||||
Module getReExportedModule() {
|
||||
Stages::Imports::ref() and
|
||||
result.getFile() = this.getEnclosingModule().resolve(this.getImportedPath())
|
||||
or
|
||||
result = this.resolveFromTypeRoot()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a module in a `node_modules/@types/` folder that matches the imported module name.
|
||||
*/
|
||||
private Module resolveFromTypeRoot() {
|
||||
result.getFile() =
|
||||
min(TypeRootFolder typeRoot |
|
||||
|
|
||||
typeRoot.getModuleFile(this.getImportedPath().getStringValue())
|
||||
order by
|
||||
typeRoot.getSearchPriority(this.getFile().getParentContainer())
|
||||
)
|
||||
result.getFile() = ImportPathResolver::resolveExpr(this.getImportedPath())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.internal.CachedStages
|
||||
private import semmle.javascript.internal.paths.PathExprResolver
|
||||
|
||||
/**
|
||||
* A module, which may either be an ECMAScript 2015-style module,
|
||||
@@ -138,39 +139,17 @@ abstract class Import extends AstNode {
|
||||
/**
|
||||
* Gets the module the path of this import resolves to.
|
||||
*/
|
||||
Module resolveImportedPath() {
|
||||
result.getFile() = this.getEnclosingModule().resolve(this.getImportedPath())
|
||||
}
|
||||
Module resolveImportedPath() { result.getFile() = this.getTargetFile() }
|
||||
|
||||
/**
|
||||
* Gets a module with a `@providesModule` JSDoc tag that matches
|
||||
* the imported path.
|
||||
* Gets the module the path of this import resolves to.
|
||||
*/
|
||||
private Module resolveAsProvidedModule() {
|
||||
exists(JSDocTag tag |
|
||||
tag.getTitle() = "providesModule" and
|
||||
tag.getParent().getComment().getTopLevel() = result and
|
||||
tag.getDescription().trim() = this.getImportedPath().getValue()
|
||||
)
|
||||
}
|
||||
File getTargetFile() { result = ImportPathResolver::resolveExpr(this.getImportedPath()) }
|
||||
|
||||
/**
|
||||
* Gets a module in a `node_modules/@types/` folder that matches the imported module name.
|
||||
* DEPRECATED. Use `getImportedModule()` instead.
|
||||
*/
|
||||
private Module resolveFromTypeRoot() {
|
||||
result.getFile() =
|
||||
min(TypeRootFolder typeRoot |
|
||||
|
|
||||
typeRoot.getModuleFile(this.getImportedPath().getValue())
|
||||
order by
|
||||
typeRoot.getSearchPriority(this.getFile().getParentContainer())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the imported module, as determined by the TypeScript compiler, if any.
|
||||
*/
|
||||
private Module resolveFromTypeScriptSymbol() {
|
||||
deprecated Module resolveFromTypeScriptSymbol() {
|
||||
exists(CanonicalName symbol |
|
||||
ast_node_symbol(this, symbol) and
|
||||
ast_node_symbol(result, symbol)
|
||||
@@ -190,13 +169,7 @@ abstract class Import extends AstNode {
|
||||
Stages::Imports::ref() and
|
||||
if exists(this.resolveExternsImport())
|
||||
then result = this.resolveExternsImport()
|
||||
else (
|
||||
result = this.resolveAsProvidedModule() or
|
||||
result = this.resolveImportedPath() or
|
||||
result = this.resolveFromTypeRoot() or
|
||||
result = this.resolveFromTypeScriptSymbol() or
|
||||
result = resolveNeighbourPackage(this.getImportedPath().getValue())
|
||||
)
|
||||
else result = this.resolveImportedPath()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,28 +177,3 @@ abstract class Import extends AstNode {
|
||||
*/
|
||||
abstract DataFlow::Node getImportedModuleNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a module imported from another package in the same repository.
|
||||
*
|
||||
* No support for importing from folders inside the other package.
|
||||
*/
|
||||
private Module resolveNeighbourPackage(PathString importPath) {
|
||||
exists(PackageJson json | importPath = json.getPackageName() and result = json.getMainModule())
|
||||
or
|
||||
exists(string package |
|
||||
result.getFile().getParentContainer() = getPackageFolder(package) and
|
||||
importPath = package + "/" + [result.getFile().getBaseName(), result.getFile().getStem()]
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the folder for a package that has name `package` according to a package.json file in the resulting folder.
|
||||
*/
|
||||
pragma[noinline]
|
||||
private Folder getPackageFolder(string package) {
|
||||
exists(PackageJson json |
|
||||
json.getPackageName() = package and
|
||||
result = json.getFile().getParentContainer()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
private import semmle.javascript.internal.paths.PathMapping
|
||||
|
||||
/**
|
||||
* A TypeScript configuration file, usually named `tsconfig.json`.
|
||||
@@ -178,3 +179,44 @@ private module ResolverConfig implements Folder::ResolveSig {
|
||||
}
|
||||
|
||||
private module Resolver = Folder::Resolve<ResolverConfig>;
|
||||
|
||||
/**
|
||||
* Gets a tsconfig file to use as fallback for handling paths in `c`.
|
||||
*
|
||||
* This holds for files and folders where no tsconfig seems to include it,
|
||||
* but it has one or more tsconfig files in parent directories.
|
||||
*/
|
||||
private TSConfig getFallbackTSConfig(Container c) {
|
||||
not c = any(TSConfig t).getAnIncludedContainer() and
|
||||
(
|
||||
c = result.getFolder()
|
||||
or
|
||||
result = getFallbackTSConfig(c.getParentContainer())
|
||||
)
|
||||
}
|
||||
|
||||
private class TSConfigPathMapping extends PathMapping, TSConfig {
|
||||
override File getAnAffectedFile() {
|
||||
result = this.getAnIncludedContainer()
|
||||
or
|
||||
this = getFallbackTSConfig(result)
|
||||
}
|
||||
|
||||
override predicate hasExactPathMapping(string pattern, Container newContext, string newPath) {
|
||||
exists(TSConfig tsconfig |
|
||||
tsconfig = this.getExtendedTSConfig*() and
|
||||
tsconfig.hasExactPathMapping(pattern, newPath) and
|
||||
newContext = tsconfig.getBaseUrlFolderOrOwnFolder()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasPrefixPathMapping(string pattern, Container newContext, string newPath) {
|
||||
exists(TSConfig tsconfig |
|
||||
tsconfig = this.getExtendedTSConfig*() and
|
||||
tsconfig.hasPrefixPathMapping(pattern, newPath) and
|
||||
newContext = tsconfig.getBaseUrlFolderOrOwnFolder()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasBaseUrl(Container base) { base = this.getBaseUrlFolder() }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
private import javascript
|
||||
|
||||
/**
|
||||
* A path expression that can be constant-folded by concatenating subexpressions.
|
||||
*/
|
||||
abstract class PathConcatenation extends Expr {
|
||||
/** Gets the separator to insert between paths */
|
||||
string getSeparator() { result = "" }
|
||||
|
||||
/** Gets the `n`th operand to concatenate. */
|
||||
abstract Expr getOperand(int n);
|
||||
}
|
||||
|
||||
private class AddExprConcatenation extends PathConcatenation, AddExpr {
|
||||
override Expr getOperand(int n) {
|
||||
n = 0 and result = this.getLeftOperand()
|
||||
or
|
||||
n = 1 and result = this.getRightOperand()
|
||||
}
|
||||
}
|
||||
|
||||
private class TemplateConcatenation extends PathConcatenation, TemplateLiteral {
|
||||
override Expr getOperand(int n) { result = this.getElement(n) }
|
||||
}
|
||||
|
||||
private class JoinCallConcatenation extends PathConcatenation, CallExpr {
|
||||
JoinCallConcatenation() {
|
||||
this.getReceiver().(VarAccess).getName() = "path" and
|
||||
this.getCalleeName() = ["join", "resolve"]
|
||||
}
|
||||
|
||||
override Expr getOperand(int n) { result = this.getArgument(n) }
|
||||
|
||||
override string getSeparator() { result = "/" }
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
private import javascript
|
||||
private import semmle.javascript.internal.paths.PackageJsonEx
|
||||
private import semmle.javascript.internal.paths.JSPaths
|
||||
private import semmle.javascript.internal.paths.PathMapping
|
||||
private import semmle.javascript.internal.paths.PathConcatenation
|
||||
private import semmle.javascript.dataflow.internal.DataFlowNode
|
||||
|
||||
/**
|
||||
* Gets the file to import when an imported path resolves to the given `folder`.
|
||||
*/
|
||||
File getFileFromFolderImport(Folder folder) {
|
||||
result = folder.getJavaScriptFileOrTypings("index")
|
||||
or
|
||||
// Note that unlike "exports" paths, "main" and "module" also take effect when the package
|
||||
// is imported via a relative path, e.g. `require("..")` targeting a folder with a package.json file.
|
||||
exists(PackageJsonEx pkg |
|
||||
pkg.getFolder() = folder and
|
||||
result = pkg.getMainFileOrBestGuess()
|
||||
)
|
||||
}
|
||||
|
||||
private Variable dirnameVar() { result.getName() = "__dirname" }
|
||||
|
||||
private Variable filenameVar() { result.getName() = "__filename" }
|
||||
|
||||
private signature predicate exprSig(Expr e);
|
||||
|
||||
module ResolveExpr<exprSig/1 shouldResolveExpr> {
|
||||
/** Holds if we need the constant string-value of `node`. */
|
||||
private predicate needsConstantFolding(EarlyStageNode node) {
|
||||
exists(Expr e |
|
||||
shouldResolveExpr(e) and
|
||||
node = TValueNode(e)
|
||||
)
|
||||
or
|
||||
exists(EarlyStageNode needsFolding | needsConstantFolding(needsFolding) |
|
||||
DataFlow::Impl::earlyStageImmediateFlowStep(node, needsFolding)
|
||||
or
|
||||
exists(PathConcatenation joiner |
|
||||
needsFolding = TValueNode(joiner) and
|
||||
node = TValueNode(joiner.getOperand(_))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the constant-value of `node` */
|
||||
language[monotonicAggregates]
|
||||
private string getValue(EarlyStageNode node) {
|
||||
needsConstantFolding(node) and
|
||||
(
|
||||
exists(Expr e | node = TValueNode(e) |
|
||||
result = e.getStringValue()
|
||||
or
|
||||
e = dirnameVar().getAnAccess() and
|
||||
result = "./" // Ensure the path gets interpreted relative to the current directory
|
||||
or
|
||||
e = filenameVar().getAnAccess() and
|
||||
result = "./" + e.getFile().getBaseName()
|
||||
)
|
||||
or
|
||||
exists(EarlyStageNode pred |
|
||||
DataFlow::Impl::earlyStageImmediateFlowStep(pred, node) and
|
||||
result = getValue(pred)
|
||||
)
|
||||
or
|
||||
exists(PathConcatenation join |
|
||||
node = TValueNode(join) and
|
||||
result =
|
||||
strictconcat(int n, EarlyStageNode child, string sep |
|
||||
child = TValueNode(join.getOperand(n)) and sep = join.getSeparator()
|
||||
|
|
||||
getValue(child), sep order by n
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final private class FinalExpr = Expr;
|
||||
|
||||
private class RelevantExpr extends FinalExpr {
|
||||
RelevantExpr() { shouldResolveExpr(this) }
|
||||
|
||||
/** Gets the string-value of this path. */
|
||||
string getValue() { result = getValue(TValueNode(this)) }
|
||||
|
||||
/** Gets a path mapping affecting this path. */
|
||||
pragma[nomagic]
|
||||
PathMapping getAPathMapping() { result.getAnAffectedFile() = this.getFile() }
|
||||
|
||||
/** Gets the NPM package name from the beginning of this path. */
|
||||
pragma[nomagic]
|
||||
string getPackagePrefix() { result = this.getValue().(FilePath).getPackagePrefix() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `expr` matches a path mapping, and should thus be resolved as `newPath` relative to `base`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate resolveViaPathMapping(RelevantExpr expr, Container base, string newPath) {
|
||||
// Handle path mappings such as `{ "paths": { "@/*": "./src/*" }}` in a tsconfig.json file
|
||||
exists(PathMapping mapping, string value |
|
||||
mapping = expr.getAPathMapping() and
|
||||
value = expr.getValue()
|
||||
|
|
||||
mapping.hasExactPathMapping(value, base, newPath)
|
||||
or
|
||||
exists(string pattern, string suffix, string mappedPath |
|
||||
mapping.hasPrefixPathMapping(pattern, base, mappedPath) and
|
||||
value = pattern + suffix and
|
||||
newPath = mappedPath + suffix
|
||||
)
|
||||
)
|
||||
or
|
||||
// Handle imports referring to a package by name, where we have a package.json
|
||||
// file for that package in the codebase. This is treated separately from PathMapping for performance
|
||||
// reasons, as there can be a large number of packages which affect all files in the project.
|
||||
//
|
||||
// This part only handles the "exports" property of package.json. "main" and "modules" are
|
||||
// handled further down because their semantics are easier to handle there.
|
||||
exists(PackageJsonEx pkg, string packageName, string remainder |
|
||||
packageName = expr.getPackagePrefix() and
|
||||
pkg.getDeclaredPackageName() = packageName and
|
||||
remainder = expr.getValue().suffix(packageName.length()).regexpReplaceAll("^[/\\\\]", "")
|
||||
|
|
||||
// "exports": { ".": "./foo.js" }
|
||||
// "exports": { "./foo.js": "./foo/impl.js" }
|
||||
pkg.hasExactPathMappingTo(remainder, base) and
|
||||
newPath = ""
|
||||
or
|
||||
// "exports": { "./*": "./foo/*" }
|
||||
exists(string prefix |
|
||||
pkg.hasPrefixPathMappingTo(prefix, base) and
|
||||
remainder = prefix + newPath
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noopt]
|
||||
private predicate relativePathExpr(RelevantExpr expr, Container base, FilePath path) {
|
||||
expr instanceof RelevantExpr and
|
||||
path = expr.getValue() and
|
||||
path.isDotRelativePath() and
|
||||
exists(File file |
|
||||
file = expr.getFile() and
|
||||
base = file.getParentContainer()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Container getJSDocProvidedModule(string moduleName) {
|
||||
exists(JSDocTag tag |
|
||||
tag.getTitle() = "providesModule" and
|
||||
tag.getDescription().trim() = moduleName and
|
||||
tag.getFile() = result
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `expr` should be resolved as `path` relative to `base`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate shouldResolve(RelevantExpr expr, Container base, FilePath path) {
|
||||
// Relative paths are resolved from their enclosing folder
|
||||
relativePathExpr(expr, base, path)
|
||||
or
|
||||
resolveViaPathMapping(expr, base, path)
|
||||
or
|
||||
// Resolve from baseUrl of relevant tsconfig.json file
|
||||
path = expr.getValue() and
|
||||
not path.isDotRelativePath() and
|
||||
expr.getAPathMapping().hasBaseUrl(base)
|
||||
or
|
||||
// If the path starts with the name of a package, resolve relative to the directory of that package.
|
||||
// Note that `getFileFromFolderImport` may subsequently redirect this to the package's "main",
|
||||
// so we don't have to deal with that here.
|
||||
exists(PackageJson pkg, string packageName |
|
||||
packageName = expr.getPackagePrefix() and
|
||||
pkg.getDeclaredPackageName() = packageName and
|
||||
path = expr.getValue().suffix(packageName.length()) and
|
||||
base = pkg.getFolder()
|
||||
)
|
||||
or
|
||||
base = getJSDocProvidedModule(expr.getValue()) and
|
||||
path = ""
|
||||
}
|
||||
|
||||
private module ResolverConfig implements Folder::ResolveSig {
|
||||
predicate shouldResolve(Container base, string path) { shouldResolve(_, base, path) }
|
||||
|
||||
predicate getAnAdditionalChild = JSPaths::getAnAdditionalChild/2;
|
||||
}
|
||||
|
||||
private module Resolver = Folder::Resolve<ResolverConfig>;
|
||||
|
||||
private Container resolvePathExpr1(RelevantExpr expr) {
|
||||
exists(Container base, string path |
|
||||
shouldResolve(expr, base, path) and
|
||||
result = Resolver::resolve(base, path)
|
||||
)
|
||||
}
|
||||
|
||||
File resolveExpr(RelevantExpr expr) {
|
||||
result = resolvePathExpr1(expr)
|
||||
or
|
||||
result = getFileFromFolderImport(resolvePathExpr1(expr))
|
||||
}
|
||||
|
||||
module Debug {
|
||||
class PathExprToDebug extends RelevantExpr {
|
||||
PathExprToDebug() { this.getValue() = "vs/nls" }
|
||||
}
|
||||
|
||||
query PathExprToDebug pathExprs() { any() }
|
||||
|
||||
query string getPackagePrefixFromPathExpr_(PathExprToDebug expr) {
|
||||
result = expr.getPackagePrefix()
|
||||
}
|
||||
|
||||
query predicate resolveViaPathMapping_(PathExprToDebug expr, Container base, string newPath) {
|
||||
resolveViaPathMapping(expr, base, newPath)
|
||||
}
|
||||
|
||||
query predicate shouldResolve_(PathExprToDebug expr, Container base, string newPath) {
|
||||
shouldResolve(expr, base, newPath)
|
||||
}
|
||||
|
||||
query Container resolvePathExpr1_(PathExprToDebug expr) { result = resolvePathExpr1(expr) }
|
||||
|
||||
query File resolveExpr_(PathExprToDebug expr) { result = resolveExpr(expr) }
|
||||
|
||||
// Some predicates that are usually small enough that they don't need restriction
|
||||
query File getPackageMainFile(PackageJsonEx pkg) { result = pkg.getMainFile() }
|
||||
|
||||
query predicate guessPackageJsonMain1_ = guessPackageJsonMain1/1;
|
||||
|
||||
query predicate guessPackageJsonMain2_ = guessPackageJsonMain2/1;
|
||||
|
||||
query predicate getFileFromFolderImport_ = getFileFromFolderImport/1;
|
||||
}
|
||||
}
|
||||
|
||||
private predicate isImportPathExpr(Expr e) {
|
||||
e = any(Import imprt).getImportedPath()
|
||||
or
|
||||
e = any(ReExportDeclaration decl).getImportedPath()
|
||||
}
|
||||
|
||||
/** Resolves paths in imports and re-exports. */
|
||||
module ImportPathResolver = ResolveExpr<isImportPathExpr/1>;
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Provides an extensible mechanism for modeling path mappings.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
private import semmle.javascript.TSConfig
|
||||
|
||||
/**
|
||||
* A `tsconfig.json`-like configuration object that can affect import resolution via path mappings.
|
||||
*/
|
||||
abstract class PathMapping extends Locatable {
|
||||
/**
|
||||
* Gets a file affected by this path mapping.
|
||||
*/
|
||||
abstract File getAnAffectedFile();
|
||||
|
||||
/**
|
||||
* Holds if imports paths exactly matching `pattern` should be redirected to `newPath`
|
||||
* resolved relative to `newContext`.
|
||||
*/
|
||||
predicate hasExactPathMapping(string pattern, Container newContext, string newPath) { none() }
|
||||
|
||||
/**
|
||||
* Holds if imports paths starting with `pattern` should have the matched prefix replaced by `newPath`
|
||||
* and then resolved relative to `newContext`.
|
||||
*/
|
||||
predicate hasPrefixPathMapping(string pattern, Container newContext, string newPath) { none() }
|
||||
|
||||
/** Holds if non-relative paths in affected files should be resolved relative to `base`. */
|
||||
predicate hasBaseUrl(Container base) { none() }
|
||||
}
|
||||
@@ -94,14 +94,12 @@ requireImport
|
||||
| a.js:3:6:3:23 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | <toplevel> |
|
||||
| a.js:4:6:4:29 | require ... /d.js') | ./sub/../d.js | d.js:1:1:7:15 | <toplevel> |
|
||||
| a.js:7:1:7:18 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | <toplevel> |
|
||||
| a.js:10:1:10:18 | require(__dirname) | | index.js:1:1:3:0 | <toplevel> |
|
||||
| a.js:11:1:11:25 | require ... + '/e') | /e | e.js:1:1:6:0 | <toplevel> |
|
||||
| a.js:12:1:12:28 | require ... + 'c') | ./sub/c | sub/c.js:1:1:4:0 | <toplevel> |
|
||||
| b.js:1:1:1:18 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | <toplevel> |
|
||||
| d.js:7:1:7:14 | require('foo') | foo | sub/f.js:1:1:4:17 | <toplevel> |
|
||||
| index.js:2:1:2:41 | require ... b.js")) | /index.js/../b.js | b.js:1:1:8:0 | <toplevel> |
|
||||
| mjs-files/require-from-js.js:1:12:1:36 | require ... on-me') | ./depend-on-me | mjs-files/depend-on-me.mjs:1:1:7:1 | <toplevel> |
|
||||
| mjs-files/require-from-js.js:2:12:2:39 | require ... me.js') | ./depend-on-me.js | mjs-files/depend-on-me.js:1:1:8:0 | <toplevel> |
|
||||
| mjs-files/require-from-js.js:2:12:2:39 | require ... me.js') | ./depend-on-me.js | mjs-files/depend-on-me.mjs:1:1:7:1 | <toplevel> |
|
||||
| mjs-files/require-from-js.js:3:12:3:40 | require ... e.mjs') | ./depend-on-me.mjs | mjs-files/depend-on-me.mjs:1:1:7:1 | <toplevel> |
|
||||
| reexport/b.js:1:11:1:24 | require("./a") | ./a | reexport/a.js:1:1:3:1 | <toplevel> |
|
||||
| sub/c.js:1:1:1:15 | require('../a') | ../a | a.js:1:1:14:0 | <toplevel> |
|
||||
|
||||
@@ -4,4 +4,4 @@ import "../lib/split.d.ts"; // $ importTarget=DeclarationFiles/lib/split.d.ts
|
||||
|
||||
import "../lib/typescript"; // $ importTarget=DeclarationFiles/lib/typescript.ts
|
||||
import "../lib/typescript.js"; // $ importTarget=DeclarationFiles/lib/typescript.ts
|
||||
import "../lib/typescript.d.ts"; // $ importTarget=DeclarationFiles/lib/typescript.d.ts SPURIOUS: importTarget=DeclarationFiles/lib/typescript.ts
|
||||
import "../lib/typescript.d.ts"; // $ importTarget=DeclarationFiles/lib/typescript.d.ts
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import "@/both" // $ importTarget=Fallback/lib1/both.ts
|
||||
import "@/both" // $ importTarget=Fallback/lib1/both.ts SPURIOUS: importTarget=Fallback/lib2/both.ts
|
||||
import "@/only1" // $ importTarget=Fallback/lib1/only1.ts
|
||||
import "@/only2" // $ importTarget=Fallback/lib2/only2.ts
|
||||
import "@/differentExtension" // $ importTarget=Fallback/lib2/differentExtension.ts
|
||||
import "@/differentExtension.js" // $ importTarget=Fallback/lib2/differentExtension.ts
|
||||
import "@/differentExtension" // $ importTarget=Fallback/lib2/differentExtension.ts SPURIOUS: importTarget=Fallback/lib1/differentExtension.js
|
||||
import "@/differentExtension.js" // $ importTarget=Fallback/lib2/differentExtension.ts SPURIOUS: importTarget=Fallback/lib1/differentExtension.js
|
||||
|
||||
import "@/subdir" // $ importTarget=Fallback/lib1/subdir/index.ts
|
||||
import "@/subdir/both" // $ importTarget=Fallback/lib1/subdir/both.ts
|
||||
import "@/subdir" // $ importTarget=Fallback/lib1/subdir/index.ts SPURIOUS: importTarget=Fallback/lib2/subdir/index.ts
|
||||
import "@/subdir/both" // $ importTarget=Fallback/lib1/subdir/both.ts SPURIOUS: importTarget=Fallback/lib2/subdir/both.ts
|
||||
import "@/subdir/only1" // $ importTarget=Fallback/lib1/subdir/only1.ts
|
||||
import "@/subdir/only2" // $ importTarget=Fallback/lib2/subdir/only2.ts
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import './PackageWithMain/main'; // $ importTarget=PackageWithMain/main.js
|
||||
import '@example/package-with-main'; // $ importTarget=PackageWithMain/main.js
|
||||
|
||||
import './PackageWithModuleMain'; // $ MISSING: importTarget=PackageWithModuleMain/main.js
|
||||
import './PackageWithModuleMain'; // $ importTarget=PackageWithModuleMain/main.js
|
||||
import '@example/package-with-module-main'; // $ importTarget=PackageWithModuleMain/main.js
|
||||
|
||||
import './PackageWithExports'; // Not a valid import
|
||||
import './PackageWithExports/fake-file'; // Not a valid import
|
||||
import './PackageWithExports/star/foo'; // Not a valid import
|
||||
import '@example/package-with-exports'; // $ importTarget=PackageWithExports/main.js
|
||||
import '@example/package-with-exports/fake-file'; // $ MISSING: importTarget=PackageWithExports/fake-file-impl.js
|
||||
import '@example/package-with-exports/star/foo'; // $ MISSING: importTarget=PackageWithExports/star-impl/foo.js
|
||||
import '@example/package-with-exports/fake-file'; // $ importTarget=PackageWithExports/fake-file-impl.js
|
||||
import '@example/package-with-exports/star/foo'; // $ importTarget=PackageWithExports/star-impl/foo.js
|
||||
|
||||
import './PackageIndexFile'; // $ importTarget=PackageIndexFile/index.js
|
||||
import '@example/package-with-index-file'; // $ importTarget=PackageIndexFile/index.js
|
||||
|
||||
import './PackageGuess1'; // $ MISSING: importTarget=PackageGuess1/src/index.ts
|
||||
import './PackageGuess1'; // $ importTarget=PackageGuess1/src/index.ts
|
||||
import '@example/package-guess1'; // $ importTarget=PackageGuess1/src/index.ts
|
||||
|
||||
import './PackageGuess2'; // $ MISSING: importTarget=PackageGuess2/blah/stuff.ts
|
||||
import './PackageGuess2'; // $ importTarget=PackageGuess2/blah/stuff.ts
|
||||
import '@example/package-guess2'; // $ importTarget=PackageGuess2/blah/stuff.ts
|
||||
|
||||
import './PackageWithMainExt'; // $ importTarget=PackageWithMainExt/lib/main.ts
|
||||
@@ -25,11 +25,11 @@ import '@example/package-with-main-ext'; // $ importTarget=PackageWithMainExt/li
|
||||
|
||||
import './TSConfigOutDir/customOutDir/foo.js'; // $ importTarget=TSConfigOutDir/src/foo.ts
|
||||
|
||||
import './MainIsFolder'; // $ MISSING: importTarget=MainIsFolder/src/index.ts
|
||||
import './MainIsFolder'; // $ importTarget=MainIsFolder/src/index.ts
|
||||
import '@example/main-is-folder'; // $ importTarget=MainIsFolder/src/index.ts
|
||||
|
||||
import './DistContainsSrc'; // $ MISSING: importTarget=DistContainsSrc/src/foo.ts
|
||||
import './DistContainsSrc'; // $ importTarget=DistContainsSrc/src/foo.ts
|
||||
|
||||
import './MinifiedMain'; // $ MISSING: importTarget=MinifiedMain/src/library.ts
|
||||
import './MinifiedMain'; // $ importTarget=MinifiedMain/src/library.ts
|
||||
|
||||
import './RootDir/my-out/foo.js'; // $ importTarget=RootDir/my-root/foo.ts
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
| DeclarationFiles/src/main.ts:5:1:5:27 | import ... cript"; | DeclarationFiles/lib/typescript.ts |
|
||||
| DeclarationFiles/src/main.ts:6:1:6:30 | import ... pt.js"; | DeclarationFiles/lib/typescript.ts |
|
||||
| DeclarationFiles/src/main.ts:7:1:7:32 | import ... .d.ts"; | DeclarationFiles/lib/typescript.d.ts |
|
||||
| DeclarationFiles/src/main.ts:7:1:7:32 | import ... .d.ts"; | DeclarationFiles/lib/typescript.ts |
|
||||
| DirnameImports/main.js:4:1:4:33 | require ... et.js') | DirnameImports/target.js |
|
||||
| DirnameImports/main.js:5:1:5:40 | require ... et.js') | DirnameImports/nested/target.js |
|
||||
| DirnameImports/main.js:6:1:6:45 | require ... es.ts') | import-packages.ts |
|
||||
@@ -69,12 +68,17 @@
|
||||
| Extended/src/main.ts:25:1:25:20 | import "@/index.ts"; | Extended/lib/index.ts |
|
||||
| Extended/src/main.ts:26:1:26:20 | import "@/index.js"; | Extended/lib/index.ts |
|
||||
| Fallback/src/main.ts:1:1:1:15 | import "@/both" | Fallback/lib1/both.ts |
|
||||
| Fallback/src/main.ts:1:1:1:15 | import "@/both" | Fallback/lib2/both.ts |
|
||||
| Fallback/src/main.ts:2:1:2:16 | import "@/only1" | Fallback/lib1/only1.ts |
|
||||
| Fallback/src/main.ts:3:1:3:16 | import "@/only2" | Fallback/lib2/only2.ts |
|
||||
| Fallback/src/main.ts:4:1:4:29 | import ... ension" | Fallback/lib1/differentExtension.js |
|
||||
| Fallback/src/main.ts:4:1:4:29 | import ... ension" | Fallback/lib2/differentExtension.ts |
|
||||
| Fallback/src/main.ts:5:1:5:32 | import ... ion.js" | Fallback/lib1/differentExtension.js |
|
||||
| Fallback/src/main.ts:5:1:5:32 | import ... ion.js" | Fallback/lib2/differentExtension.ts |
|
||||
| Fallback/src/main.ts:7:1:7:17 | import "@/subdir" | Fallback/lib1/subdir/index.ts |
|
||||
| Fallback/src/main.ts:7:1:7:17 | import "@/subdir" | Fallback/lib2/subdir/index.ts |
|
||||
| Fallback/src/main.ts:8:1:8:22 | import ... r/both" | Fallback/lib1/subdir/both.ts |
|
||||
| Fallback/src/main.ts:8:1:8:22 | import ... r/both" | Fallback/lib2/subdir/both.ts |
|
||||
| Fallback/src/main.ts:9:1:9:23 | import ... /only1" | Fallback/lib1/subdir/only1.ts |
|
||||
| Fallback/src/main.ts:10:1:10:23 | import ... /only2" | Fallback/lib2/subdir/only2.ts |
|
||||
| JSDocProvide/main.js:1:1:1:43 | import ... r/baz'; | JSDocProvide/lib.js |
|
||||
@@ -98,14 +102,22 @@
|
||||
| NodeModules/subfolder/src/main.ts:2:1:2:13 | import 'bar'; | NodeModules/subfolder/node_modules/bar/index.js |
|
||||
| import-packages.ts:1:1:1:32 | import ... /main'; | PackageWithMain/main.js |
|
||||
| import-packages.ts:2:1:2:36 | import ... -main'; | PackageWithMain/main.js |
|
||||
| import-packages.ts:4:1:4:33 | import ... eMain'; | PackageWithModuleMain/main.js |
|
||||
| import-packages.ts:5:1:5:43 | import ... -main'; | PackageWithModuleMain/main.js |
|
||||
| import-packages.ts:10:1:10:39 | import ... ports'; | PackageWithExports/main.js |
|
||||
| import-packages.ts:11:1:11:49 | import ... -file'; | PackageWithExports/fake-file-impl.js |
|
||||
| import-packages.ts:12:1:12:48 | import ... r/foo'; | PackageWithExports/star-impl/foo.js |
|
||||
| import-packages.ts:14:1:14:28 | import ... xFile'; | PackageIndexFile/index.js |
|
||||
| import-packages.ts:15:1:15:42 | import ... -file'; | PackageIndexFile/index.js |
|
||||
| import-packages.ts:17:1:17:25 | import ... uess1'; | PackageGuess1/src/index.ts |
|
||||
| import-packages.ts:18:1:18:33 | import ... uess1'; | PackageGuess1/src/index.ts |
|
||||
| import-packages.ts:20:1:20:25 | import ... uess2'; | PackageGuess2/blah/stuff.ts |
|
||||
| import-packages.ts:21:1:21:33 | import ... uess2'; | PackageGuess2/blah/stuff.ts |
|
||||
| import-packages.ts:23:1:23:30 | import ... inExt'; | PackageWithMainExt/lib/main.ts |
|
||||
| import-packages.ts:24:1:24:40 | import ... n-ext'; | PackageWithMainExt/lib/main.ts |
|
||||
| import-packages.ts:26:1:26:46 | import ... oo.js'; | TSConfigOutDir/src/foo.ts |
|
||||
| import-packages.ts:28:1:28:24 | import ... older'; | MainIsFolder/src/index.ts |
|
||||
| import-packages.ts:29:1:29:33 | import ... older'; | MainIsFolder/src/index.ts |
|
||||
| import-packages.ts:31:1:31:27 | import ... nsSrc'; | DistContainsSrc/src/foo.ts |
|
||||
| import-packages.ts:33:1:33:24 | import ... dMain'; | MinifiedMain/src/library.ts |
|
||||
| import-packages.ts:35:1:35:33 | import ... oo.js'; | RootDir/my-root/foo.ts |
|
||||
|
||||
Reference in New Issue
Block a user