Skip to content

Commit 42c03ab

Browse files
committed
JS: Add flow steps through dynamic imports
1 parent a9adb29 commit 42c03ab

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

javascript/ql/src/semmle/javascript/Promises.qll

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,3 +641,39 @@ private module ClosurePromise {
641641
override predicate step(DataFlow::Node src, DataFlow::Node dst) { src = pred and dst = this }
642642
}
643643
}
644+
645+
private module DynamicImportSteps {
646+
/**
647+
* A step from an export value to its uses via dynamic imports.
648+
*
649+
* For example:
650+
* ```js
651+
* // foo.js
652+
* export default Foo
653+
*
654+
* // bar.js
655+
* let Foo = await import('./foo');
656+
* ```
657+
*/
658+
class DynamicImportStep extends PreCallGraphStep {
659+
override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
660+
exists(DynamicImportExpr imprt |
661+
pred = imprt.getImportedModule().getAnExportedValue("default") and
662+
succ = imprt.flow() and
663+
prop = Promises::valueProp()
664+
)
665+
}
666+
667+
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
668+
// Special-case code like `(await import(x)).Foo` to boost type tracking depth.
669+
exists(
670+
DynamicImportExpr imprt, string name, DataFlow::Node mid, DataFlow::SourceNode awaited
671+
|
672+
pred = imprt.getImportedModule().getAnExportedValue(name) and
673+
mid.getALocalSource() = imprt.flow() and
674+
PromiseFlow::loadStep(mid, awaited, Promises::valueProp()) and
675+
succ = awaited.getAPropertyRead(name)
676+
)
677+
}
678+
}
679+
}

0 commit comments

Comments
 (0)