referencesImport: support named exports accessed via * imports (#12603)
Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
This commit is contained in:
parent
a93bbce867
commit
774c526390
@ -164,13 +164,30 @@ export function isStatementOrBlock(this: NodePath): boolean {
|
||||
*/
|
||||
|
||||
export function referencesImport(
|
||||
this: NodePath<t.Identifier>,
|
||||
this: NodePath<t.Expression>,
|
||||
moduleSource: string,
|
||||
importName: string,
|
||||
): boolean {
|
||||
if (!this.isReferencedIdentifier()) return false;
|
||||
if (!this.isReferencedIdentifier()) {
|
||||
if (
|
||||
(this.isMemberExpression() || this.isOptionalMemberExpression()) &&
|
||||
(this.node.computed
|
||||
? t.isStringLiteral(this.node.property, { value: importName })
|
||||
: (this.node.property as t.Identifier).name === importName)
|
||||
) {
|
||||
const object = (this as NodePath<
|
||||
t.MemberExpression | t.OptionalMemberExpression
|
||||
>).get("object");
|
||||
return (
|
||||
object.isReferencedIdentifier() &&
|
||||
object.referencesImport(moduleSource, "*")
|
||||
);
|
||||
}
|
||||
|
||||
const binding = this.scope.getBinding(this.node.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
const binding = this.scope.getBinding((this.node as t.Identifier).name);
|
||||
if (!binding || binding.kind !== "module") return false;
|
||||
|
||||
const path = binding.path;
|
||||
|
||||
@ -100,4 +100,108 @@ describe("path/introspection", function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("referencesImport", function () {
|
||||
it("accepts a default import", function () {
|
||||
const program = getPath(`import dep from "source"; dep;`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "default")).toBe(true);
|
||||
});
|
||||
it("rejects a default import from the wrong module", function () {
|
||||
const program = getPath(`import dep from "wrong-source"; dep;`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "default")).toBe(false);
|
||||
});
|
||||
it("rejects a named instead of default import", function () {
|
||||
const program = getPath(`import { dep } from "source"; dep;`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "default")).toBe(false);
|
||||
});
|
||||
|
||||
it("accepts a named import", function () {
|
||||
const program = getPath(`import { dep } from "source"; dep;`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "dep")).toBe(true);
|
||||
});
|
||||
it("accepts an aliased named import", function () {
|
||||
const program = getPath(`import { dep as alias } from "source"; alias;`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "dep")).toBe(true);
|
||||
});
|
||||
it("accepts a named import via a namespace import member expression", function () {
|
||||
const program = getPath(`import * as ns from "source"; ns.dep;`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "dep")).toBe(true);
|
||||
});
|
||||
it("accepts a named import via a namespace import optional member expression", function () {
|
||||
const program = getPath(`import * as ns from "source"; ns?.dep;`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "dep")).toBe(true);
|
||||
});
|
||||
it("accepts a named import via a namespace import computed member expression", function () {
|
||||
const program = getPath(`import * as ns from "source"; ns["😅"];`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "😅")).toBe(true);
|
||||
});
|
||||
it("rejects a named import from the wrong module", function () {
|
||||
const program = getPath(`import { dep } from "wrong-source"; dep;`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "dep")).toBe(false);
|
||||
});
|
||||
it("rejects a default instead of named import", function () {
|
||||
const program = getPath(`import dep from "source"; dep;`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "dep")).toBe(false);
|
||||
});
|
||||
it('rejects the "export called *" trick', function () {
|
||||
const program = getPath(`import * as ns from "source"; ns["*"].nested;`, {
|
||||
sourceType: "module",
|
||||
plugins: ["moduleStringNames"],
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "nested")).toBe(false);
|
||||
});
|
||||
|
||||
it("accepts a namespace import", function () {
|
||||
const program = getPath(`import * as dep from "source"; dep;`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "*")).toBe(true);
|
||||
});
|
||||
it("rejects a namespace import from the wrong module", function () {
|
||||
const program = getPath(`import * as dep from "wrong-source"; dep;`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "*")).toBe(false);
|
||||
});
|
||||
it("rejects a default instead of a namespace import", () => {
|
||||
const program = getPath(`import dep from "source"; dep;`, {
|
||||
sourceType: "module",
|
||||
});
|
||||
const reference = program.get("body.1.expression");
|
||||
expect(reference.referencesImport("source", "*")).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user