зеркало из https://github.com/github/codeql.git
Merge pull request #10036 from asgerf/js/exports-handling
JS: More precise handling of "exports"
This commit is contained in:
Коммит
eaf3aa7075
|
@ -50,8 +50,23 @@ class PackageJson extends JsonObject {
|
|||
/** Gets a file for this package. */
|
||||
string getAFile() { result = this.getFiles().getElementStringValue(_) }
|
||||
|
||||
/** Gets the main module of this package. */
|
||||
string getMain() { result = MainModulePath::of(this).getValue() }
|
||||
/**
|
||||
* Gets the main module of this package.
|
||||
*
|
||||
* This can be given by the `main` or `module` property, or via the
|
||||
* `exports` property with the relative path `"."`.
|
||||
*/
|
||||
string getMain() { result = this.getExportedPath(".") }
|
||||
|
||||
/**
|
||||
* Gets the path to the file exported with the given relative path.
|
||||
*
|
||||
* This can be given by the `exports` property, but also considers `main` and
|
||||
* `module` paths to be exported under the relative path `"."`.
|
||||
*/
|
||||
string getExportedPath(string relativePath) {
|
||||
result = MainModulePath::of(this, relativePath).getValue()
|
||||
}
|
||||
|
||||
/** Gets the path of a command defined for this package. */
|
||||
string getBin(string cmd) {
|
||||
|
@ -181,6 +196,18 @@ class PackageJson extends JsonObject {
|
|||
result = min(Module m, int prio | m.getFile() = resolveMainModule(this, prio) | m order by prio)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the module exported under the given relative path.
|
||||
*
|
||||
* The main module is considered exported under the path `"."`.
|
||||
*/
|
||||
Module getExportedModule(string relativePath) {
|
||||
relativePath = "." and
|
||||
result = this.getMainModule()
|
||||
or
|
||||
result.getFile() = MainModulePath::of(this, relativePath).resolve()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `types` or `typings` field of this package.
|
||||
*/
|
||||
|
|
|
@ -93,7 +93,7 @@ private string getStem(string name) { result = name.regexpCapture("(.+?)(?:\\.([
|
|||
* Gets the main module described by `pkg` with the given `priority`.
|
||||
*/
|
||||
File resolveMainModule(PackageJson pkg, int priority) {
|
||||
exists(PathExpr main | main = MainModulePath::of(pkg) |
|
||||
exists(PathExpr main | main = MainModulePath::of(pkg, ".") |
|
||||
result = main.resolve() and priority = 0
|
||||
or
|
||||
result = tryExtensions(main.resolve(), "index", priority)
|
||||
|
@ -142,21 +142,36 @@ File resolveMainModule(PackageJson pkg, int priority) {
|
|||
private string getASrcFolderName() { result = ["ts", "js", "src", "lib"] }
|
||||
|
||||
/**
|
||||
* A JSON string in a `package.json` file specifying the path of the main
|
||||
* module of the package.
|
||||
* A JSON string in a `package.json` file specifying the path of one of the exported
|
||||
* modules of the package.
|
||||
*/
|
||||
class MainModulePath extends PathExpr, @json_string {
|
||||
PackageJson pkg;
|
||||
string relativePath;
|
||||
|
||||
MainModulePath() {
|
||||
relativePath = "." and
|
||||
this = pkg.getPropValue(["main", "module"])
|
||||
or
|
||||
this = getAJsonChild*(pkg.getPropValue("exports"))
|
||||
// { "exports": "path" } is sugar for { "exports": { ".": "path" }}
|
||||
relativePath = "." and
|
||||
this = pkg.getPropValue("exports")
|
||||
or
|
||||
exists(JsonValue val | val = pkg.getPropValue("exports").getPropValue(relativePath) |
|
||||
// Either specified directly as a string: { "./path": "./path.js" }
|
||||
this = val
|
||||
or
|
||||
// Or by module type: { "./path": { "require": "./path.cjs", ... }}
|
||||
this = val.getPropValue(_)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the `package.json` file in which this path occurs. */
|
||||
PackageJson getPackageJson() { result = pkg }
|
||||
|
||||
/** Gets the relative path under which this is exported, usually starting with a `.`. */
|
||||
string getRelativePath() { result = relativePath }
|
||||
|
||||
/** DEPRECATED: Alias for getPackageJson */
|
||||
deprecated PackageJSON getPackageJSON() { result = getPackageJson() }
|
||||
|
||||
|
@ -168,11 +183,15 @@ class MainModulePath extends PathExpr, @json_string {
|
|||
}
|
||||
}
|
||||
|
||||
/** Gets the value of a property from the JSON object `obj`. */
|
||||
private JsonValue getAJsonChild(JsonObject obj) { result = obj.getPropValue(_) }
|
||||
|
||||
module MainModulePath {
|
||||
MainModulePath of(PackageJson pkg) { result.getPackageJson() = pkg }
|
||||
/** Gets the path to the main entry point of `pkg`. */
|
||||
MainModulePath of(PackageJson pkg) { result = of(pkg, ".") }
|
||||
|
||||
/** Gets the path to the file exported from `pkg` as `relativePath`. */
|
||||
MainModulePath of(PackageJson pkg, string relativePath) {
|
||||
result.getPackageJson() = pkg and
|
||||
result.getRelativePath() = relativePath
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,7 +204,7 @@ private class FilesPath extends PathExpr, @json_string {
|
|||
|
||||
FilesPath() {
|
||||
this = pkg.getPropValue("files").(JsonArray).getElementValue(_) and
|
||||
not exists(MainModulePath::of(pkg))
|
||||
not exists(MainModulePath::of(pkg, _))
|
||||
}
|
||||
|
||||
/** Gets the `package.json` file in which this path occurs. */
|
||||
|
|
|
@ -52,7 +52,7 @@ private import NodeModuleResolutionImpl as NodeModule
|
|||
private DataFlow::Node getAValueExportedByPackage() {
|
||||
// The base case, an export from a named `package.json` file.
|
||||
result =
|
||||
getAnExportFromModule(any(PackageJson pack | exists(pack.getPackageName())).getMainModule())
|
||||
getAnExportFromModule(any(PackageJson pack | exists(pack.getPackageName())).getExportedModule(_))
|
||||
or
|
||||
// module.exports.bar.baz = result;
|
||||
exists(DataFlow::PropWrite write |
|
||||
|
|
Загрузка…
Ссылка в новой задаче