Skip to content

Commit

Permalink
referencesImport: support named exports accessed via * imports (#12603)
Browse files Browse the repository at this point in the history
Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>
  • Loading branch information
jeysal and nicolo-ribaudo committed Feb 21, 2021
1 parent a93bbce commit 774c526
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 3 deletions.
23 changes: 20 additions & 3 deletions packages/babel-traverse/src/path/introspection.ts
Expand Up @@ -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, "*")
);
}

return false;
}

const binding = this.scope.getBinding(this.node.name);
const binding = this.scope.getBinding((this.node as t.Identifier).name);
if (!binding || binding.kind !== "module") return false;

const path = binding.path;
Expand Down
104 changes: 104 additions & 0 deletions packages/babel-traverse/test/introspection.js
Expand Up @@ -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);
});
});
});

0 comments on commit 774c526

Please sign in to comment.