JS: Deprecate PathExpr and related classes

This commit is contained in:
Asger F
2025-04-29 13:22:54 +02:00
parent fe055ad603
commit ed2a832a55
30 changed files with 126 additions and 104 deletions

View File

@@ -11,5 +11,5 @@
import javascript import javascript
from ImportDeclaration id from ImportDeclaration id
where id.getImportedPath().getValue() = "react" where id.getImportedPathString() = "react"
select id select id

View File

@@ -70,7 +70,7 @@ private predicate importLookup(AstNode path, Module target, string kind) {
kind = "I" and kind = "I" and
( (
exists(Import i | exists(Import i |
path = i.getImportedPath() and path = i.getImportedPathExpr() and
target = i.getImportedModule() target = i.getImportedModule()
) )
or or

View File

@@ -61,8 +61,14 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range
result = this.getArgument(1) result = this.getArgument(1)
} }
/** DEPRECATED. Use `getDependencyExpr` instead. */
deprecated PathExpr getDependency(int i) { result = this.getDependencyExpr(i) }
/** DEPRECATED. Use `getADependencyExpr` instead. */
deprecated PathExpr getADependency() { result = this.getADependencyExpr() }
/** Gets the `i`th dependency of this module definition. */ /** Gets the `i`th dependency of this module definition. */
PathExpr getDependency(int i) { Expr getDependencyExpr(int i) {
exists(Expr expr | exists(Expr expr |
expr = this.getDependencies().getElement(i) and expr = this.getDependencies().getElement(i) and
not isPseudoDependency(expr.getStringValue()) and not isPseudoDependency(expr.getStringValue()) and
@@ -71,8 +77,8 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range
} }
/** Gets a dependency of this module definition. */ /** Gets a dependency of this module definition. */
PathExpr getADependency() { Expr getADependencyExpr() {
result = this.getDependency(_) or result = this.getDependencyExpr(_) or
result = this.getARequireCall().getAnArgument() result = this.getARequireCall().getAnArgument()
} }
@@ -233,7 +239,7 @@ private class AmdDependencyPath extends PathExprCandidate {
} }
/** A constant path element appearing in an AMD dependency expression. */ /** A constant path element appearing in an AMD dependency expression. */
private class ConstantAmdDependencyPathElement extends PathExpr, ConstantString { deprecated private class ConstantAmdDependencyPathElement extends PathExpr, ConstantString {
ConstantAmdDependencyPathElement() { this = any(AmdDependencyPath amd).getAPart() } ConstantAmdDependencyPathElement() { this = any(AmdDependencyPath amd).getAPart() }
override string getValue() { result = this.getStringValue() } override string getValue() { result = this.getStringValue() }
@@ -261,11 +267,13 @@ private predicate amdModuleTopLevel(AmdModuleDefinition def, TopLevel tl) {
* An AMD dependency, viewed as an import. * An AMD dependency, viewed as an import.
*/ */
private class AmdDependencyImport extends Import { private class AmdDependencyImport extends Import {
AmdDependencyImport() { this = any(AmdModuleDefinition def).getADependency() } AmdDependencyImport() { this = any(AmdModuleDefinition def).getADependencyExpr() }
override Module getEnclosingModule() { this = result.(AmdModule).getDefine().getADependency() } override Module getEnclosingModule() {
this = result.(AmdModule).getDefine().getADependencyExpr()
}
override PathExpr getImportedPath() { result = this } override Expr getImportedPathExpr() { result = this }
/** /**
* Gets a file that looks like it might be the target of this import. * Gets a file that looks like it might be the target of this import.
@@ -274,7 +282,7 @@ private class AmdDependencyImport extends Import {
* adding well-known JavaScript file extensions like `.js`. * adding well-known JavaScript file extensions like `.js`.
*/ */
private File guessTarget() { private File guessTarget() {
exists(PathString imported, string abspath, string dirname, string basename | exists(FilePath imported, string abspath, string dirname, string basename |
this.targetCandidate(result, abspath, imported, dirname, basename) this.targetCandidate(result, abspath, imported, dirname, basename)
| |
abspath.regexpMatch(".*/\\Q" + imported + "\\E") abspath.regexpMatch(".*/\\Q" + imported + "\\E")
@@ -296,9 +304,9 @@ private class AmdDependencyImport extends Import {
* `dirname` and `basename` to the dirname and basename (respectively) of `imported`. * `dirname` and `basename` to the dirname and basename (respectively) of `imported`.
*/ */
private predicate targetCandidate( private predicate targetCandidate(
File f, string abspath, PathString imported, string dirname, string basename File f, string abspath, FilePath imported, string dirname, string basename
) { ) {
imported = this.getImportedPath().getValue() and imported = this.getImportedPathString() and
f.getStem() = imported.getStem() and f.getStem() = imported.getStem() and
f.getAbsolutePath() = abspath and f.getAbsolutePath() = abspath and
dirname = imported.getDirName() and dirname = imported.getDirName() and

View File

@@ -92,13 +92,13 @@ private predicate hasDefaultExport(ES2015Module mod) {
class ImportDeclaration extends Stmt, Import, @import_declaration { class ImportDeclaration extends Stmt, Import, @import_declaration {
override ES2015Module getEnclosingModule() { result = this.getTopLevel() } override ES2015Module getEnclosingModule() { result = this.getTopLevel() }
override PathExpr getImportedPath() { result = this.getChildExpr(-1) }
/** /**
* INTERNAL USE ONLY. DO NOT USE. * INTERNAL USE ONLY. DO NOT USE.
*/ */
string getRawImportPath() { result = this.getChildExpr(-1).getStringValue() } string getRawImportPath() { result = this.getChildExpr(-1).getStringValue() }
override Expr getImportedPathExpr() { result = this.getChildExpr(-1) }
/** /**
* Gets the object literal passed as part of the `with` (or `assert`) clause in this import declaration. * Gets the object literal passed as part of the `with` (or `assert`) clause in this import declaration.
* *
@@ -155,7 +155,7 @@ class ImportDeclaration extends Stmt, Import, @import_declaration {
} }
/** A literal path expression appearing in an `import` declaration. */ /** A literal path expression appearing in an `import` declaration. */
private class LiteralImportPath extends PathExpr, ConstantString { deprecated private class LiteralImportPath extends PathExpr, ConstantString {
LiteralImportPath() { exists(ImportDeclaration req | this = req.getChildExpr(-1)) } LiteralImportPath() { exists(ImportDeclaration req | this = req.getChildExpr(-1)) }
override string getValue() { result = this.getStringValue() } override string getValue() { result = this.getStringValue() }
@@ -736,7 +736,7 @@ abstract class ReExportDeclaration extends ExportDeclaration {
} }
/** A literal path expression appearing in a re-export declaration. */ /** A literal path expression appearing in a re-export declaration. */
private class LiteralReExportPath extends PathExpr, ConstantString { deprecated private class LiteralReExportPath extends PathExpr, ConstantString {
LiteralReExportPath() { exists(ReExportDeclaration bred | this = bred.getImportedPath()) } LiteralReExportPath() { exists(ReExportDeclaration bred | this = bred.getImportedPath()) }
override string getValue() { result = this.getStringValue() } override string getValue() { result = this.getStringValue() }

View File

@@ -2821,7 +2821,7 @@ class DynamicImportExpr extends @dynamic_import, Expr, Import {
result = this.getSource().getFirstControlFlowNode() result = this.getSource().getFirstControlFlowNode()
} }
override PathExpr getImportedPath() { result = this.getSource() } override Expr getImportedPathExpr() { result = this.getSource() }
/** /**
* Gets the second "argument" to the import expression, that is, the `Y` in `import(X, Y)`. * Gets the second "argument" to the import expression, that is, the `Y` in `import(X, Y)`.
@@ -2852,7 +2852,7 @@ class DynamicImportExpr extends @dynamic_import, Expr, Import {
} }
/** A literal path expression appearing in a dynamic import. */ /** A literal path expression appearing in a dynamic import. */
private class LiteralDynamicImportPath extends PathExpr, ConstantString { deprecated private class LiteralDynamicImportPath extends PathExpr, ConstantString {
LiteralDynamicImportPath() { LiteralDynamicImportPath() {
exists(DynamicImportExpr di | this.getParentExpr*() = di.getSource()) exists(DynamicImportExpr di | this.getParentExpr*() = di.getSource())
} }

View File

@@ -214,7 +214,7 @@ module HTML {
result = path.regexpCapture("file://(/.*)", 1) result = path.regexpCapture("file://(/.*)", 1)
or or
not path.regexpMatch("(\\w+:)?//.*") and not path.regexpMatch("(\\w+:)?//.*") and
result = this.getSourcePath().(ScriptSrcPath).resolve(this.getSearchRoot()).toString() result = ResolveScriptSrc::resolve(this.getSearchRoot(), this.getSourcePath()).toString()
) )
} }
@@ -274,10 +274,16 @@ module HTML {
) )
} }
private module ResolverConfig implements Folder::ResolveSig {
predicate shouldResolve(Container base, string path) { scriptSrc(path, base) }
}
private module ResolveScriptSrc = Folder::Resolve<ResolverConfig>;
/** /**
* A path string arising from the `src` attribute of a `script` tag. * A path string arising from the `src` attribute of a `script` tag.
*/ */
private class ScriptSrcPath extends PathString { deprecated private class ScriptSrcPath extends PathString {
ScriptSrcPath() { scriptSrc(this, _) } ScriptSrcPath() { scriptSrc(this, _) }
override Folder getARootFolder() { scriptSrc(this, result) } override Folder getARootFolder() { scriptSrc(this, result) }

View File

@@ -69,7 +69,7 @@ abstract class Module extends TopLevel {
* This predicate is not part of the public API, it is only exposed to allow * This predicate is not part of the public API, it is only exposed to allow
* overriding by subclasses. * overriding by subclasses.
*/ */
predicate searchRoot(PathExpr path, Folder searchRoot, int priority) { deprecated predicate searchRoot(PathExpr path, Folder searchRoot, int priority) {
path.getEnclosingModule() = this and path.getEnclosingModule() = this and
priority = 0 and priority = 0 and
exists(string v | v = path.getValue() | exists(string v | v = path.getValue() |
@@ -90,7 +90,7 @@ abstract class Module extends TopLevel {
* resolves to a folder containing a main module (such as `index.js`), then * resolves to a folder containing a main module (such as `index.js`), then
* that file is the result. * that file is the result.
*/ */
File resolve(PathExpr path) { deprecated File resolve(PathExpr path) {
path.getEnclosingModule() = this and path.getEnclosingModule() = this and
( (
// handle the case where the import path is complete // handle the case where the import path is complete
@@ -123,8 +123,14 @@ abstract class Import extends AstNode {
/** Gets the module in which this import appears. */ /** Gets the module in which this import appears. */
abstract Module getEnclosingModule(); abstract Module getEnclosingModule();
/** DEPRECATED. Use `getImportedPathExpr` instead. */
deprecated PathExpr getImportedPath() { result = this.getImportedPathExpr() }
/** Gets the (unresolved) path that this import refers to. */ /** Gets the (unresolved) path that this import refers to. */
abstract PathExpr getImportedPath(); abstract Expr getImportedPathExpr();
/** Gets the imported path as a string. */
final string getImportedPathString() { result = this.getImportedPathExpr().getStringValue() }
/** /**
* Gets an externs module the path of this import resolves to. * Gets an externs module the path of this import resolves to.
@@ -133,7 +139,7 @@ abstract class Import extends AstNode {
* path is assumed to be a possible target of the import. * path is assumed to be a possible target of the import.
*/ */
Module resolveExternsImport() { Module resolveExternsImport() {
result.isExterns() and result.getName() = this.getImportedPath().getValue() result.isExterns() and result.getName() = this.getImportedPathString()
} }
/** /**
@@ -144,7 +150,7 @@ abstract class Import extends AstNode {
/** /**
* Gets the module the path of this import resolves to. * Gets the module the path of this import resolves to.
*/ */
File getTargetFile() { result = ImportPathResolver::resolveExpr(this.getImportedPath()) } File getTargetFile() { result = ImportPathResolver::resolveExpr(this.getImportedPathExpr()) }
/** /**
* DEPRECATED. Use `getImportedModule()` instead. * DEPRECATED. Use `getImportedModule()` instead.

View File

@@ -146,7 +146,7 @@ class NodeModule extends Module {
) )
} }
override predicate searchRoot(PathExpr path, Folder searchRoot, int priority) { deprecated override predicate searchRoot(PathExpr path, Folder searchRoot, int priority) {
path.getEnclosingModule() = this and path.getEnclosingModule() = this and
exists(string pathval | pathval = path.getValue() | exists(string pathval | pathval = path.getValue() |
// paths starting with `./` or `../` are resolved relative to the importing // paths starting with `./` or `../` are resolved relative to the importing
@@ -236,11 +236,6 @@ private class RequireVariable extends Variable {
} }
} }
/**
* Holds if module `m` is in file `f`.
*/
private predicate moduleInFile(Module m, File f) { m.getFile() = f }
private predicate isModuleModule(EarlyStageNode nd) { private predicate isModuleModule(EarlyStageNode nd) {
exists(ImportDeclaration imp | imp.getRawImportPath() = "module" | exists(ImportDeclaration imp | imp.getRawImportPath() = "module" |
nd = TDestructuredModuleImportNode(imp) nd = TDestructuredModuleImportNode(imp)
@@ -328,24 +323,17 @@ private predicate isRequire(EarlyStageNode nd) {
class Require extends CallExpr, Import { class Require extends CallExpr, Import {
Require() { isRequire(TValueNode(this.getCallee())) } Require() { isRequire(TValueNode(this.getCallee())) }
override PathExpr getImportedPath() { result = this.getArgument(0) } override Expr getImportedPathExpr() { result = this.getArgument(0) }
override Module getEnclosingModule() { this = result.getAnImport() } override Module getEnclosingModule() { this = result.getAnImport() }
override Module resolveImportedPath() {
moduleInFile(result, this.load(min(int prio | moduleInFile(_, this.load(prio)))))
or
not moduleInFile(_, this.load(_)) and
result = Import.super.resolveImportedPath()
}
/** /**
* Gets the file that is imported by this `require`. * Gets the file that is imported by this `require`.
* *
* The result can be a JavaScript file, a JSON file or a `.node` file. * The result can be a JavaScript file, a JSON file or a `.node` file.
* Externs files are not treated differently from other files by this predicate. * Externs files are not treated differently from other files by this predicate.
*/ */
File getImportedFile() { result = this.load(min(int prio | exists(this.load(prio)))) } deprecated File getImportedFile() { result = this.load(min(int prio | exists(this.load(prio)))) }
/** /**
* Gets the file that this `require` refers to (which may not be a JavaScript file), * Gets the file that this `require` refers to (which may not be a JavaScript file),
@@ -402,8 +390,8 @@ class Require extends CallExpr, Import {
* predicate `tryExtensions` that handles the repeated distinction between * predicate `tryExtensions` that handles the repeated distinction between
* `.js`, `.json` and `.node`. * `.js`, `.json` and `.node`.
*/ */
private File load(int priority) { deprecated private File load(int priority) {
exists(int r | this.getEnclosingModule().searchRoot(this.getImportedPath(), _, r) | exists(int r | this.getEnclosingModule().searchRoot(this.getImportedPathExpr(), _, r) |
result = loadAsFile(this, r, priority - prioritiesPerCandidate() * r) or result = loadAsFile(this, r, priority - prioritiesPerCandidate() * r) or
result = result =
loadAsDirectory(this, r, loadAsDirectory(this, r,
@@ -415,7 +403,7 @@ class Require extends CallExpr, Import {
} }
/** An argument to `require` or `require.resolve`, considered as a path expression. */ /** An argument to `require` or `require.resolve`, considered as a path expression. */
private class RequirePath extends PathExprCandidate { deprecated private class RequirePath extends PathExprCandidate {
RequirePath() { RequirePath() {
this = any(Require req).getArgument(0) this = any(Require req).getArgument(0)
or or
@@ -428,14 +416,14 @@ private class RequirePath extends PathExprCandidate {
} }
/** A constant path element appearing in a call to `require` or `require.resolve`. */ /** A constant path element appearing in a call to `require` or `require.resolve`. */
private class ConstantRequirePathElement extends PathExpr, ConstantString { deprecated private class ConstantRequirePathElement extends PathExpr, ConstantString {
ConstantRequirePathElement() { this = any(RequirePath rp).getAPart() } ConstantRequirePathElement() { this = any(RequirePath rp).getAPart() }
override string getValue() { result = this.getStringValue() } override string getValue() { result = this.getStringValue() }
} }
/** A `__dirname` path expression. */ /** A `__dirname` path expression. */
private class DirNamePath extends PathExpr, VarAccess { deprecated private class DirNamePath extends PathExpr, VarAccess {
DirNamePath() { DirNamePath() {
this.getName() = "__dirname" and this.getName() = "__dirname" and
this.getVariable().getScope() instanceof ModuleScope this.getVariable().getScope() instanceof ModuleScope
@@ -445,7 +433,7 @@ private class DirNamePath extends PathExpr, VarAccess {
} }
/** A `__filename` path expression. */ /** A `__filename` path expression. */
private class FileNamePath extends PathExpr, VarAccess { deprecated private class FileNamePath extends PathExpr, VarAccess {
FileNamePath() { FileNamePath() {
this.getName() = "__filename" and this.getName() = "__filename" and
this.getVariable().getScope() instanceof ModuleScope this.getVariable().getScope() instanceof ModuleScope
@@ -458,7 +446,7 @@ private class FileNamePath extends PathExpr, VarAccess {
* A path expression of the form `path.join(p, "...")` where * A path expression of the form `path.join(p, "...")` where
* `p` is also a path expression. * `p` is also a path expression.
*/ */
private class JoinedPath extends PathExpr, @call_expr { deprecated private class JoinedPath extends PathExpr, @call_expr {
JoinedPath() { JoinedPath() {
exists(MethodCallExpr call | call = this | exists(MethodCallExpr call | call = this |
call.getReceiver().(VarAccess).getName() = "path" and call.getReceiver().(VarAccess).getName() = "path" and

View File

@@ -45,7 +45,7 @@ int numberOfExtensions() { result = count(getFileExtensionPriority(_)) }
* Gets the resolution target with the given `priority` of `req` * Gets the resolution target with the given `priority` of `req`
* when resolved from the root with priority `rootPriority`. * when resolved from the root with priority `rootPriority`.
*/ */
File loadAsFile(Require req, int rootPriority, int priority) { deprecated File loadAsFile(Require req, int rootPriority, int priority) {
exists(PathExpr path | path = req.getImportedPath() | exists(PathExpr path | path = req.getImportedPath() |
result = path.resolve(rootPriority) and priority = 0 result = path.resolve(rootPriority) and priority = 0
or or
@@ -60,7 +60,7 @@ File loadAsFile(Require req, int rootPriority, int priority) {
* with the given `priority` of `req` when resolved from the root with * with the given `priority` of `req` when resolved from the root with
* priority `rootPriority`. * priority `rootPriority`.
*/ */
File loadAsDirectory(Require req, int rootPriority, int priority) { deprecated File loadAsDirectory(Require req, int rootPriority, int priority) {
exists(Folder dir | dir = req.getImportedPath().resolve(rootPriority) | exists(Folder dir | dir = req.getImportedPath().resolve(rootPriority) |
result = resolveMainModule(dir.(NpmPackage).getPackageJson(), priority, ".") or result = resolveMainModule(dir.(NpmPackage).getPackageJson(), priority, ".") or
result = tryExtensions(dir, "index", priority - (numberOfExtensions() + 1)) result = tryExtensions(dir, "index", priority - (numberOfExtensions() + 1))
@@ -99,7 +99,7 @@ private string getStem(string name) {
* Gets a file that a main module from `pkg` exported as `mainPath` with the given `priority`. * Gets a file that a main module from `pkg` exported as `mainPath` with the given `priority`.
* `mainPath` is "." if it's the main module of the package. * `mainPath` is "." if it's the main module of the package.
*/ */
private File resolveMainPath(PackageJson pkg, string mainPath, int priority) { deprecated private File resolveMainPath(PackageJson pkg, string mainPath, int priority) {
exists(PathExpr main | main = MainModulePath::of(pkg, mainPath) | exists(PathExpr main | main = MainModulePath::of(pkg, mainPath) |
result = main.resolve() and priority = 0 result = main.resolve() and priority = 0
or or
@@ -132,7 +132,7 @@ private File resolveMainPath(PackageJson pkg, string mainPath, int priority) {
/** /**
* Gets the main module described by `pkg` with the given `priority`. * Gets the main module described by `pkg` with the given `priority`.
*/ */
File resolveMainModule(PackageJson pkg, int priority, string exportPath) { deprecated File resolveMainModule(PackageJson pkg, int priority, string exportPath) {
result = resolveMainPath(pkg, exportPath, priority) result = resolveMainPath(pkg, exportPath, priority)
or or
exportPath = "." and exportPath = "." and
@@ -178,7 +178,7 @@ private string getASrcFolderName() { result = ["ts", "js", "src", "lib"] }
* A JSON string in a `package.json` file specifying the path of one of the exported * A JSON string in a `package.json` file specifying the path of one of the exported
* modules of the package. * modules of the package.
*/ */
class MainModulePath extends PathExpr, @json_string { deprecated class MainModulePath extends PathExpr, @json_string {
PackageJson pkg; PackageJson pkg;
MainModulePath() { MainModulePath() {
@@ -228,7 +228,7 @@ private string getExportRelativePath(JsonValue part) {
result.matches(".%") result.matches(".%")
} }
module MainModulePath { deprecated module MainModulePath {
/** Gets the path to the main entry point of `pkg`. */ /** Gets the path to the main entry point of `pkg`. */
MainModulePath of(PackageJson pkg) { result = of(pkg, ".") } MainModulePath of(PackageJson pkg) { result = of(pkg, ".") }
@@ -244,7 +244,7 @@ module MainModulePath {
* These files are often imported directly from a client when a "main" module is not specified. * These files are often imported directly from a client when a "main" module is not specified.
* For performance reasons this only exists if there is no "main" field in the `package.json` file. * For performance reasons this only exists if there is no "main" field in the `package.json` file.
*/ */
private class FilesPath extends PathExpr, @json_string { deprecated private class FilesPath extends PathExpr, @json_string {
PackageJson pkg; PackageJson pkg;
FilesPath() { FilesPath() {
@@ -263,7 +263,7 @@ private class FilesPath extends PathExpr, @json_string {
} }
} }
private module FilesPath { deprecated private module FilesPath {
FilesPath of(PackageJson pkg) { result.getPackageJson() = pkg } FilesPath of(PackageJson pkg) { result.getPackageJson() = pkg }
} }
@@ -271,7 +271,7 @@ private module FilesPath {
* A JSON string in a `package.json` file specifying the path of the * A JSON string in a `package.json` file specifying the path of the
* TypeScript typings entry point. * TypeScript typings entry point.
*/ */
class TypingsModulePathString extends PathString { deprecated class TypingsModulePathString extends PathString {
PackageJson pkg; PackageJson pkg;
TypingsModulePathString() { TypingsModulePathString() {
@@ -288,7 +288,7 @@ class TypingsModulePathString extends PathString {
} }
/** Companion module to the `TypingsModulePathString` class. */ /** Companion module to the `TypingsModulePathString` class. */
module TypingsModulePathString { deprecated module TypingsModulePathString {
/** Get the typings path for the given `package.json` file. */ /** Get the typings path for the given `package.json` file. */
TypingsModulePathString of(PackageJson pkg) { result.getPackageJson() = pkg } TypingsModulePathString of(PackageJson pkg) { result.getPackageJson() = pkg }
} }

View File

@@ -9,13 +9,13 @@ private import semmle.javascript.dataflow.internal.DataFlowNode
/** /**
* Internal representation of paths as lists of components. * Internal representation of paths as lists of components.
*/ */
private newtype TPath = deprecated private newtype TPath =
/** A root path. */ /** A root path. */
TRootPath(string root) { TRootPath(string root) {
root = any(Folder f | not exists(f.getParentContainer())).getAbsolutePath() root = any(Folder f | not exists(f.getParentContainer())).getAbsolutePath()
} or } or
/** A path of the form `<parent>/<component>`. */ /** A path of the form `<parent>/<component>`. */
TConsPath(Path parent, string component) { deprecated TConsPath(Path parent, string component) {
// make sure we can represent paths of files in snapshot // make sure we can represent paths of files in snapshot
exists(Folder f | f = parent.getContainer() | exists(f.getChildContainer(component))) exists(Folder f | f = parent.getContainer() | exists(f.getChildContainer(component)))
or or
@@ -32,7 +32,7 @@ private newtype TPath =
* Gets a textual representation of path `p` using slashes as delimiters; * Gets a textual representation of path `p` using slashes as delimiters;
* the empty path is represented as the empty string `""`. * the empty path is represented as the empty string `""`.
*/ */
private string pp(TPath p) { deprecated private string pp(TPath p) {
p = TRootPath(result + "/") p = TRootPath(result + "/")
or or
exists(TPath parent, string component | p = TConsPath(parent, component) | exists(TPath parent, string component | p = TConsPath(parent, component) |
@@ -45,7 +45,7 @@ private string pp(TPath p) {
* which may (but does not have to) correspond to a file or folder included * which may (but does not have to) correspond to a file or folder included
* in the snapshot. * in the snapshot.
*/ */
class Path extends TPath { deprecated class Path extends TPath {
/** /**
* Gets the file or folder referred to by this path, if it exists. * Gets the file or folder referred to by this path, if it exists.
*/ */
@@ -60,14 +60,14 @@ class Path extends TPath {
/** /**
* The empty path, which refers to the file system root. * The empty path, which refers to the file system root.
*/ */
private class RootPath extends Path, TRootPath { deprecated private class RootPath extends Path, TRootPath {
override string toString() { this = TRootPath(result) } override string toString() { this = TRootPath(result) }
} }
/** /**
* A non-empty path of the form `<parent>/<component>`. * A non-empty path of the form `<parent>/<component>`.
*/ */
private class ConsPath extends Path, TConsPath { deprecated private class ConsPath extends Path, TConsPath {
/** Gets the parent path of this path. */ /** Gets the parent path of this path. */
Path getParent() { this = TConsPath(result, _) } Path getParent() { this = TConsPath(result, _) }
@@ -170,7 +170,7 @@ class FilePath extends string {
* usually resolved relative to the module's folder, with a default * usually resolved relative to the module's folder, with a default
* lookup path as the fallback. * lookup path as the fallback.
*/ */
abstract class PathString extends FilePath { abstract deprecated class PathString extends FilePath {
bindingset[this] bindingset[this]
PathString() { any() } PathString() { any() }
@@ -196,7 +196,7 @@ abstract class PathString extends FilePath {
* components of this path refers to when resolved relative to the * components of this path refers to when resolved relative to the
* given `root` folder. * given `root` folder.
*/ */
private Path resolveUpTo(PathString p, int n, Folder root, boolean inTS) { deprecated private Path resolveUpTo(PathString p, int n, Folder root, boolean inTS) {
n = 0 and result.getContainer() = root and root = p.getARootFolder() and inTS = false n = 0 and result.getContainer() = root and root = p.getARootFolder() and inTS = false
or or
exists(Path base, string next | next = getComponent(p, n - 1, base, root, inTS) | exists(Path base, string next | next = getComponent(p, n - 1, base, root, inTS) |
@@ -225,7 +225,7 @@ private Path resolveUpTo(PathString p, int n, Folder root, boolean inTS) {
* Supports that the root directory might be compiled output from TypeScript. * Supports that the root directory might be compiled output from TypeScript.
* `inTS` is true if the result is TypeScript that is compiled into the path specified by `str`. * `inTS` is true if the result is TypeScript that is compiled into the path specified by `str`.
*/ */
private string getComponent(PathString str, int n, Path base, Folder root, boolean inTS) { deprecated private string getComponent(PathString str, int n, Path base, Folder root, boolean inTS) {
exists(boolean prevTS | exists(boolean prevTS |
base = resolveUpTo(str, n, root, prevTS) and base = resolveUpTo(str, n, root, prevTS) and
( (
@@ -248,7 +248,7 @@ private string getComponent(PathString str, int n, Path base, Folder root, boole
/** /**
* Predicates for resolving imports to compiled TypeScript. * Predicates for resolving imports to compiled TypeScript.
*/ */
private module TypeScriptOutDir { deprecated private module TypeScriptOutDir {
/** /**
* Gets a folder of TypeScript files that is compiled to JavaScript files in `outdir` relative to a `parent`. * Gets a folder of TypeScript files that is compiled to JavaScript files in `outdir` relative to a `parent`.
*/ */
@@ -340,7 +340,7 @@ private module TypeScriptOutDir {
* as their highest-priority root, with default library paths as additional roots * as their highest-priority root, with default library paths as additional roots
* of lower priority. * of lower priority.
*/ */
abstract class PathExpr extends Locatable { abstract deprecated class PathExpr extends Locatable {
/** Gets the (unresolved) path represented by this expression. */ /** Gets the (unresolved) path represented by this expression. */
abstract string getValue(); abstract string getValue();
@@ -413,7 +413,7 @@ abstract class PathExpr extends Locatable {
} }
/** A path string derived from a path expression. */ /** A path string derived from a path expression. */
private class PathExprString extends PathString { deprecated private class PathExprString extends PathString {
PathExprString() { this = any(PathExpr pe).getValue() } PathExprString() { this = any(PathExpr pe).getValue() }
override Folder getARootFolder() { override Folder getARootFolder() {
@@ -422,13 +422,13 @@ private class PathExprString extends PathString {
} }
pragma[nomagic] pragma[nomagic]
private EarlyStageNode getAPathExprAlias(PathExpr expr) { deprecated private EarlyStageNode getAPathExprAlias(PathExpr expr) {
DataFlow::Impl::earlyStageImmediateFlowStep(TValueNode(expr), result) DataFlow::Impl::earlyStageImmediateFlowStep(TValueNode(expr), result)
or or
DataFlow::Impl::earlyStageImmediateFlowStep(getAPathExprAlias(expr), result) DataFlow::Impl::earlyStageImmediateFlowStep(getAPathExprAlias(expr), result)
} }
private class PathExprFromAlias extends PathExpr { deprecated private class PathExprFromAlias extends PathExpr {
private PathExpr other; private PathExpr other;
PathExprFromAlias() { TValueNode(this) = getAPathExprAlias(other) } PathExprFromAlias() { TValueNode(this) = getAPathExprAlias(other) }
@@ -444,7 +444,7 @@ private class PathExprFromAlias extends PathExpr {
* A path expression of the form `p + q`, where both `p` and `q` * A path expression of the form `p + q`, where both `p` and `q`
* are path expressions. * are path expressions.
*/ */
private class ConcatPath extends PathExpr { deprecated private class ConcatPath extends PathExpr {
ConcatPath() { ConcatPath() {
exists(AddExpr add | this = add | exists(AddExpr add | this = add |
add.getLeftOperand() instanceof PathExpr and add.getLeftOperand() instanceof PathExpr and

View File

@@ -207,7 +207,7 @@ class ExternalModuleReference extends Expr, Import, @external_module_reference {
/** Gets the expression specifying the module. */ /** Gets the expression specifying the module. */
Expr getExpression() { result = this.getChildExpr(0) } Expr getExpression() { result = this.getChildExpr(0) }
override PathExpr getImportedPath() { result = this.getExpression() } override Expr getImportedPathExpr() { result = this.getExpression() }
override Module getEnclosingModule() { result = this.getTopLevel() } override Module getEnclosingModule() { result = this.getTopLevel() }
@@ -221,7 +221,7 @@ class ExternalModuleReference extends Expr, Import, @external_module_reference {
} }
/** A literal path expression appearing in an external module reference. */ /** A literal path expression appearing in an external module reference. */
private class LiteralExternalModulePath extends PathExpr, ConstantString { deprecated private class LiteralExternalModulePath extends PathExpr, ConstantString {
LiteralExternalModulePath() { LiteralExternalModulePath() {
exists(ExternalModuleReference emr | this.getParentExpr*() = emr.getExpression()) exists(ExternalModuleReference emr | this.getParentExpr*() = emr.getExpression())
} }
@@ -743,7 +743,7 @@ class TypeAccess extends @typeaccess, TypeExpr, TypeRef {
* For non-relative imports, it is the import path itself. * For non-relative imports, it is the import path itself.
*/ */
private string getImportName(Import imprt) { private string getImportName(Import imprt) {
exists(string path | path = imprt.getImportedPath().getValue() | exists(string path | path = imprt.getImportedPathString() |
if path.regexpMatch("[./].*") if path.regexpMatch("[./].*")
then result = imprt.getImportedModule().getFile().getRelativePath() then result = imprt.getImportedModule().getFile().getRelativePath()
else result = path else result = path
@@ -1731,7 +1731,7 @@ class TSGlobalDeclImport extends DataFlow::ModuleImportNode::Range {
pkg = tt.getExpressionName() and pkg = tt.getExpressionName() and
// then, check pkg is imported as "import * as pkg from path" // then, check pkg is imported as "import * as pkg from path"
i.getLocal().getVariable() = pkg.getVariable() and i.getLocal().getVariable() = pkg.getVariable() and
path = i.getImportedPath().getValue() and path = i.getImportedPathString() and
// finally, "this" needs to be a reference to gv // finally, "this" needs to be a reference to gv
this = DataFlow::exprNode(gv.getAnAccess()) this = DataFlow::exprNode(gv.getAnAccess())
) )

View File

@@ -738,7 +738,7 @@ module ModuleImportNode {
DefaultRange() { DefaultRange() {
exists(Import i | exists(Import i |
this = i.getImportedModuleNode() and this = i.getImportedModuleNode() and
i.getImportedPath().getValue() = path i.getImportedPathString() = path
) )
or or
// AMD require // AMD require

View File

@@ -25,7 +25,7 @@ private class AnalyzedImportSpecifier extends AnalyzedVarDef, @import_specifier
override predicate isIncomplete(DataFlow::Incompleteness cause) { override predicate isIncomplete(DataFlow::Incompleteness cause) {
// mark as incomplete if the import could rely on the lookup path // mark as incomplete if the import could rely on the lookup path
mayDependOnLookupPath(id.getImportedPath().getValue()) and mayDependOnLookupPath(id.getImportedPathString()) and
cause = "import" cause = "import"
or or
// mark as incomplete if we cannot fully analyze this import // mark as incomplete if we cannot fully analyze this import
@@ -260,7 +260,7 @@ private class AnalyzedAmdImport extends AnalyzedPropertyRead, DataFlow::Node {
Module required; Module required;
AnalyzedAmdImport() { AnalyzedAmdImport() {
exists(AmdModule amd, PathExpr dep | exists(AmdModule amd, Expr dep |
exists(Parameter p | exists(Parameter p |
amd.getDefine().dependencyParameter(dep, p) and amd.getDefine().dependencyParameter(dep, p) and
this = DataFlow::parameterNode(p) this = DataFlow::parameterNode(p)

View File

@@ -151,6 +151,11 @@ class ExternalNpmDependency extends NpmDependency {
} }
} }
pragma[nomagic]
private string getPackagePrefix(Import i) {
result = i.getImportedPathString().(FilePath).getPackagePrefix()
}
/** /**
* Holds if import `i` may refer to the declared dependency `dep` of package `pkg`, * Holds if import `i` may refer to the declared dependency `dep` of package `pkg`,
* where the result value is the nesting depth of the file containing `i` within `pkg`. * where the result value is the nesting depth of the file containing `i` within `pkg`.
@@ -159,7 +164,7 @@ private int importsDependency(Import i, NpmPackage pkg, NpmDependency dep) {
exists(string name | exists(string name |
dep = pkg.getPackageJson().getADependenciesObject(_).getPropValue(name) and dep = pkg.getPackageJson().getADependenciesObject(_).getPropValue(name) and
not exists(i.getImportedModule()) and not exists(i.getImportedModule()) and
i.getImportedPath().getComponent(0) = name and name = getPackagePrefix(i) and
i.getEnclosingModule() = pkg.getAModule() and i.getEnclosingModule() = pkg.getAModule() and
result = distance(pkg, i.getFile()) result = distance(pkg, i.getFile())
) )

View File

@@ -32,7 +32,7 @@ pragma[nomagic]
private predicate isAngularTopLevel(TopLevel tl) { private predicate isAngularTopLevel(TopLevel tl) {
exists(Import imprt | exists(Import imprt |
imprt.getTopLevel() = tl and imprt.getTopLevel() = tl and
imprt.getImportedPath().getValue() = "angular" imprt.getImportedPathString() = "angular"
) )
or or
exists(GlobalVarAccess global | exists(GlobalVarAccess global |

View File

@@ -139,7 +139,7 @@ module Babel {
/** /**
* An import path expression that may be transformed by `babel-plugin-root-import`. * An import path expression that may be transformed by `babel-plugin-root-import`.
*/ */
private class BabelRootTransformedPathExpr extends PathExpr, Expr { deprecated private class BabelRootTransformedPathExpr extends PathExpr, Expr {
RootImportConfig plugin; RootImportConfig plugin;
string prefix; string prefix;
string mappedPrefix; string mappedPrefix;
@@ -167,7 +167,7 @@ module Babel {
/** /**
* An import path transformed by `babel-plugin-root-import`. * An import path transformed by `babel-plugin-root-import`.
*/ */
private class BabelRootTransformedPath extends PathString { deprecated private class BabelRootTransformedPath extends PathString {
BabelRootTransformedPathExpr pathExpr; BabelRootTransformedPathExpr pathExpr;
BabelRootTransformedPath() { this = pathExpr.getValue() } BabelRootTransformedPath() { this = pathExpr.getValue() }

View File

@@ -36,7 +36,7 @@ module LazyCache {
override Module getEnclosingModule() { result = this.getTopLevel() } override Module getEnclosingModule() { result = this.getTopLevel() }
override PathExpr getImportedPath() { result = this.getArgument(0) } override Expr getImportedPathExpr() { result = this.getArgument(0) }
private LazyCacheVariable getVariable() { result = cache } private LazyCacheVariable getVariable() { result = cache }
@@ -58,7 +58,7 @@ module LazyCache {
} }
/** A constant path element appearing in a call to a lazy-cache object. */ /** A constant path element appearing in a call to a lazy-cache object. */
private class LazyCachePathExpr extends PathExpr, ConstantString { deprecated private class LazyCachePathExpr extends PathExpr, ConstantString {
LazyCachePathExpr() { this = any(LazyCacheImport rp).getArgument(0) } LazyCachePathExpr() { this = any(LazyCacheImport rp).getArgument(0) }
override string getValue() { result = this.getStringValue() } override string getValue() { result = this.getStringValue() }

View File

@@ -733,7 +733,7 @@ private class ReactRouterSource extends ClientSideRemoteFlowSource {
* Holds if `mod` transitively depends on `react-router-dom`. * Holds if `mod` transitively depends on `react-router-dom`.
*/ */
private predicate dependsOnReactRouter(Module mod) { private predicate dependsOnReactRouter(Module mod) {
mod.getAnImport().getImportedPath().getValue() = "react-router-dom" mod.getAnImport().getImportedPathString() = "react-router-dom"
or or
dependsOnReactRouter(mod.getAnImportedModule()) dependsOnReactRouter(mod.getAnImportedModule())
} }

View File

@@ -442,7 +442,7 @@ module Vue {
override DataFlow::SourceNode getASource() { override DataFlow::SourceNode getASource() {
exists(Import imprt | exists(Import imprt |
imprt.getImportedPath().resolve() instanceof VueFile and imprt.getTargetFile() instanceof VueFile and
result = imprt.getImportedModuleNode() result = imprt.getImportedModuleNode()
) )
} }
@@ -494,7 +494,7 @@ module Vue {
// There is no explicit `new Vue()` call in .vue files, so instead get all the imports // There is no explicit `new Vue()` call in .vue files, so instead get all the imports
// of the .vue file. // of the .vue file.
exists(Import imprt | exists(Import imprt |
imprt.getImportedPath().resolve() = file and imprt.getTargetFile() = file and
result.asSource() = imprt.getImportedModuleNode() result.asSource() = imprt.getImportedModuleNode()
) )
} }

View File

@@ -58,7 +58,7 @@ predicate parseTypeString(string rawType, string package, string qualifiedName)
predicate isPackageUsed(string package) { predicate isPackageUsed(string package) {
package = "global" package = "global"
or or
package = any(JS::Import imp).getImportedPath().getValue() package = any(JS::Import imp).getImportedPathString()
or or
any(JS::TypeName t).hasQualifiedName(package, _) any(JS::TypeName t).hasQualifiedName(package, _)
or or

View File

@@ -240,7 +240,7 @@ module ResolveExpr<exprSig/1 shouldResolveExpr> {
} }
private predicate isImportPathExpr(Expr e) { private predicate isImportPathExpr(Expr e) {
e = any(Import imprt).getImportedPath() e = any(Import imprt).getImportedPathExpr()
or or
e = any(ReExportDeclaration decl).getImportedPath() e = any(ReExportDeclaration decl).getImportedPath()
} }

View File

@@ -88,7 +88,7 @@ module ExternalApiUsedWithUntrustedData {
not path instanceof SafeExternalApiPackage and not path instanceof SafeExternalApiPackage and
// Exclude paths that can be resolved to a file in the project // Exclude paths that can be resolved to a file in the project
not exists(Import imprt | not exists(Import imprt |
imprt.getImportedPath().getValue() = path and exists(imprt.getImportedModule()) imprt.getImportedPathString() = path and exists(imprt.getImportedModule())
) )
) )
or or

View File

@@ -152,4 +152,4 @@ where cycleAlert(mod, import_, importedModule, access)
select access, select access,
access.getName() + " is uninitialized if $@ is loaded first in the cyclic import:" + " " + access.getName() + " is uninitialized if $@ is loaded first in the cyclic import:" + " " +
repr(import_) + " => " + min(pathToModule(importedModule, mod, _)) + " => " + repr(import_) + repr(import_) + " => " + min(pathToModule(importedModule, mod, _)) + " => " + repr(import_) +
".", import_.getImportedPath(), importedModule.getName() ".", import_.getImportedPathExpr(), importedModule.getName()

View File

@@ -24,7 +24,7 @@ PackageJson getClosestPackageJson(Folder f) {
from Require r, string path, string mod from Require r, string path, string mod
where where
path = r.getImportedPath().getValue() and path = r.getImportedPathString() and
// the imported module is the initial segment of the path, up to // the imported module is the initial segment of the path, up to
// `/` or the end of the string, whichever comes first; we exclude // `/` or the end of the string, whichever comes first; we exclude
// local paths starting with `.` or `/`, since they might refer to files // local paths starting with `.` or `/`, since they might refer to files

View File

@@ -23,7 +23,17 @@ predicate declaresDependency(NpmPackage pkg, string name, JsonValue dep) {
/** /**
* Gets a path expression in a module belonging to `pkg`. * Gets a path expression in a module belonging to `pkg`.
*/ */
PathExpr getAPathExpr(NpmPackage pkg) { result.getEnclosingModule() = pkg.getAModule() } Expr getAPathExpr(NpmPackage pkg) {
exists(Import imprt |
result = imprt.getImportedPathExpr() and
pkg.getAModule() = imprt.getEnclosingModule()
)
or
exists(ReExportDeclaration decl |
result = decl.getImportedPath() and
pkg.getAModule() = decl.getEnclosingModule()
)
}
/** /**
* Gets a URL-valued attribute in a module or HTML file belonging to `pkg`. * Gets a URL-valued attribute in a module or HTML file belonging to `pkg`.
@@ -56,9 +66,8 @@ predicate usesDependency(NpmPackage pkg, string name) {
( (
// there is a path expression (e.g., in a `require` or `import`) that // there is a path expression (e.g., in a `require` or `import`) that
// references `pkg` // references `pkg`
exists(PathExpr path | path = getAPathExpr(pkg) | exists(Expr path | path = getAPathExpr(pkg) |
// check whether the path is `name` or starts with `name/`, ignoring a prefix that ends with '!' (example: "scriptloader!moment") path.getStringValue().(FilePath).getPackagePrefix() = name
path.getValue().regexpMatch("(.*!)?\\Q" + name + "\\E(/.*)?")
) )
or or
// there is an HTML URL attribute that may reference `pkg` // there is an HTML URL attribute that may reference `pkg`

View File

@@ -18,8 +18,8 @@ query predicate amdModuleDefinition(AmdModuleDefinition mod, DataFlow::SourceNod
mod.getFactoryNode() = factory mod.getFactoryNode() = factory
} }
query predicate amdModuleDependencies(AmdModuleDefinition mod, PathExpr dependency) { query predicate amdModuleDependencies(AmdModuleDefinition mod, Expr dependency) {
dependency = mod.getADependency() dependency = mod.getADependencyExpr()
} }
query predicate amdModuleExportedSymbol(AmdModule m, string sym) { sym = m.getAnExportedSymbol() } query predicate amdModuleExportedSymbol(AmdModule m, string sym) { sym = m.getAnExportedSymbol() }

View File

@@ -22,8 +22,8 @@ query predicate test_ImportNamespaceSpecifier(ImportNamespaceSpecifier ins) { an
query predicate test_ImportSpecifiers(ImportSpecifier is, VarDecl res) { res = is.getLocal() } query predicate test_ImportSpecifiers(ImportSpecifier is, VarDecl res) { res = is.getLocal() }
query predicate test_Imports(ImportDeclaration id, PathExpr res0, int res1) { query predicate test_Imports(ImportDeclaration id, Expr res0, int res1) {
res0 = id.getImportedPath() and res1 = count(id.getASpecifier()) res0 = id.getImportedPathExpr() and res1 = count(id.getASpecifier())
} }
query predicate test_Module_exports(Module m, string name, DataFlow::Node exportValue) { query predicate test_Module_exports(Module m, string name, DataFlow::Node exportValue) {

View File

@@ -26,7 +26,7 @@ query predicate require(Require r) { any() }
query predicate requireImport(Require r, string path, Module mod) { query predicate requireImport(Require r, string path, Module mod) {
exists(string fullpath, string prefix | exists(string fullpath, string prefix |
fullpath = r.getImportedPath().getValue() and fullpath = r.getImportedPathString() and
sourceLocationPrefix(prefix) and sourceLocationPrefix(prefix) and
path = fullpath.replaceAll(prefix, "") and path = fullpath.replaceAll(prefix, "") and
mod = r.getImportedModule() mod = r.getImportedModule()

View File

@@ -5,7 +5,7 @@ query predicate dataFlowModuleImports(string name, DataFlow::SourceNode imp) {
} }
query predicate imports(Import imprt, string path, Module mod) { query predicate imports(Import imprt, string path, Module mod) {
path = imprt.getImportedPath().getValue() and path = imprt.getImportedPathString() and
mod = imprt.getImportedModule() mod = imprt.getImportedModule()
} }

View File

@@ -1,4 +1,4 @@
import javascript import javascript
from Import imprt from Import imprt
select imprt, imprt.getImportedPath().getValue(), imprt.getImportedModule() select imprt, imprt.getImportedPathString(), imprt.getImportedModule()