Skip to content

Commit bb91df8

Browse files
committed
JS: Add helper for doing path resolution with JS rules
1 parent 59e1cbc commit bb91df8

File tree

1 file changed

+70
-0
lines changed
  • javascript/ql/lib/semmle/javascript/internal/paths

1 file changed

+70
-0
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* Provides predicates for use in `Folder::ResolveSig` in order to resolve
3+
* paths using JavaScript semantics.
4+
*/
5+
6+
private import javascript
7+
private import semmle.javascript.TSConfig
8+
9+
/**
10+
* Gets a folder name that is a common source folder name.
11+
*/
12+
string getASrcFolderName() { result = ["ts", "js", "src", "lib"] }
13+
14+
/**
15+
* Gets a folder name that is a common build output folder name.
16+
*/
17+
string getABuildOutputFolderName() { result = ["dist", "build", "out", "lib"] }
18+
19+
/**
20+
* Provides predicates for use in a `Folder::ResolveSig` in order to resolve
21+
* paths using JavaScript semantics.
22+
*
23+
* This accounts for two things:
24+
* - automatic file extensions (e.g `./foo` may resolve to `./foo.js`)
25+
* - mapping compiled-generated files back to their original source files
26+
*/
27+
module JSPaths {
28+
private Container getAnAdditionalChildFromBuildMapping(Container base, string name) {
29+
// When importing a .js file, map to the original file that compiles to the .js file.
30+
exists(string stem |
31+
result = base.(Folder).getJavaScriptFileOrTypings(stem) and
32+
name = stem + ".js"
33+
)
34+
or
35+
// Redirect './bar' to 'foo' given a tsconfig like:
36+
//
37+
// { include: ["foo"], compilerOptions: { outDir: "./bar" }}
38+
//
39+
exists(TSConfig tsconfig |
40+
name =
41+
tsconfig.getCompilerOptions().getPropStringValue("outDir").regexpReplaceAll("^\\./", "") and
42+
base = tsconfig.getFolder() and
43+
result = tsconfig.getEffectiveRootDir()
44+
)
45+
}
46+
47+
/**
48+
* Gets an additional child of `base` to include when resolving JS paths.
49+
*/
50+
pragma[nomagic]
51+
Container getAnAdditionalChild(Container base, string name) {
52+
// Automatically fill in file extensions
53+
result = base.(Folder).getJavaScriptFileOrTypings(name)
54+
or
55+
result = getAnAdditionalChildFromBuildMapping(base, name)
56+
or
57+
// Heuristic version of the above based on commonly used source and build folder names
58+
not exists(getAnAdditionalChildFromBuildMapping(base, name)) and
59+
exists(Folder folder | base = folder |
60+
folder = any(PackageJson pkg).getFolder() and
61+
name = getABuildOutputFolderName() and
62+
not exists(folder.getJavaScriptFileOrTypings(name)) and
63+
(
64+
result = folder.getChildContainer(getASrcFolderName())
65+
or
66+
result = folder
67+
)
68+
)
69+
}
70+
}

0 commit comments

Comments
 (0)