JS: Refactor 'default' import interop

This commit is contained in:
Asger F
2025-09-10 12:19:36 +02:00
parent 046d0d4938
commit dacc9e26e9
3 changed files with 52 additions and 8 deletions

View File

@@ -137,17 +137,26 @@ class ImportDeclaration extends Stmt, Import, @import_declaration {
is instanceof ImportNamespaceSpecifier and
count(this.getASpecifier()) = 1
or
// For compatibility with the non-standard implementation of default imports,
// treat default imports as namespace imports in cases where it can't cause ambiguity
// between named exports and the properties of a default-exported object.
not this.getImportedModule().(ES2015Module).hasBothNamedAndDefaultExports() and
is.getImportedName() = "default"
result = this.getAmbiguousDefaultImportNode()
)
or
// `import { createServer } from 'http'`
result = DataFlow::destructuredModuleImportNode(this)
}
/**
* Gets the data flow node corresponding to the `foo` in `import foo from "somewhere"`.
*
* This refers to the default import, but some non-standard compilers will treat it as a namespace
* import. In order to support both interpretations, it is considered an "ambiguous default import".
*
* Note that renamed default imports, such as `import { default as foo } from "somewhere"`,
* are not considered ambiguous, and will not be reported by this predicate.
*/
DataFlow::Node getAmbiguousDefaultImportNode() {
result = DataFlow::valueNode(this.getASpecifier().(ImportDefaultSpecifier))
}
/** Holds if this is declared with the `type` keyword, so it only imports types. */
predicate isTypeOnly() { has_type_keyword(this) }