From 1d775d0a7c54253f76584fb74a2a94483c8ca2a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Wed, 1 Sep 2021 10:38:42 -0400 Subject: [PATCH 1/6] docs: add comments on binding kind --- packages/babel-traverse/src/scope/binding.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/babel-traverse/src/scope/binding.ts b/packages/babel-traverse/src/scope/binding.ts index 8c6ce408b2fe..ea521ffac864 100644 --- a/packages/babel-traverse/src/scope/binding.ts +++ b/packages/babel-traverse/src/scope/binding.ts @@ -3,14 +3,14 @@ import type * as t from "@babel/types"; import type Scope from "./index"; type BindingKind = - | "var" - | "let" - | "const" - | "module" - | "hoisted" - | "param" - | "local" - | "unknown"; + | "var" /* var declarator */ + | "let" /* let declarator, class declaration id, catch clause parameters */ + | "const" /* const declarator */ + | "module" /* import specifiers */ + | "hoisted" /* function declaration id */ + | "param" /* function declaration parameters */ + | "local" /* function expression id, class expression id */ + | "unknown"; /* export specifiers */ /** * This class is responsible for a binding inside of a scope. * From 2dc24295c76a99a61a9933254d13c6989f97c6cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Wed, 1 Sep 2021 10:51:19 -0400 Subject: [PATCH 2/6] refactor: simplify For collector visitor --- packages/babel-traverse/src/scope/index.ts | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/babel-traverse/src/scope/index.ts b/packages/babel-traverse/src/scope/index.ts index 8f44f2ff1c03..40fa7b9f8727 100644 --- a/packages/babel-traverse/src/scope/index.ts +++ b/packages/babel-traverse/src/scope/index.ts @@ -5,7 +5,6 @@ import type { TraverseOptions } from "../index"; import Binding from "./binding"; import globals from "globals"; import { - FOR_INIT_KEYS, NOT_LOCAL_BINDING, callExpression, cloneNode, @@ -224,16 +223,13 @@ interface CollectVisitorState { } const collectorVisitor: Visitor = { - For(path) { - for (const key of FOR_INIT_KEYS) { - // todo: might be not needed with improvement to babel-types - const declar = path.get(key) as NodePath; - // delegate block scope handling to the `BlockScoped` method - if (declar.isVar()) { - const parentScope = - path.scope.getFunctionParent() || path.scope.getProgramParent(); - parentScope.registerBinding("var", declar); - } + ForStatement(path) { + const declar = path.get("init"); + // delegate block scope handling to the `BlockScoped` method + if (declar.isVar()) { + const { scope } = path; + const parentScope = scope.getFunctionParent() || scope.getProgramParent(); + parentScope.registerBinding("var", declar); } }, @@ -269,6 +265,12 @@ const collectorVisitor: Visitor = { if (left.isPattern() || left.isIdentifier()) { state.constantViolations.push(path); } + // delegate block scope handling to the `BlockScoped` method + else if (left.isVar()) { + const { scope } = path; + const parentScope = scope.getFunctionParent() || scope.getProgramParent(); + parentScope.registerBinding("var", left); + } }, ExportDeclaration: { From eca3e1d74a36cbfeb4f943ff270f1d60548d1058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Wed, 1 Sep 2021 11:07:57 -0400 Subject: [PATCH 3/6] getBinding does not return falsy values --- packages/babel-traverse/src/scope/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/babel-traverse/src/scope/index.ts b/packages/babel-traverse/src/scope/index.ts index 40fa7b9f8727..d6589580cc9b 100644 --- a/packages/babel-traverse/src/scope/index.ts +++ b/packages/babel-traverse/src/scope/index.ts @@ -284,12 +284,12 @@ const collectorVisitor: Visitor = { if (!id) return; const binding = scope.getBinding(id.name); - if (binding) binding.reference(path); + binding?.reference(path); } else if (isVariableDeclaration(declar)) { for (const decl of declar.declarations) { for (const name of Object.keys(getBindingIdentifiers(decl))) { const binding = scope.getBinding(name); - if (binding) binding.reference(path); + binding?.reference(path); } } } From f2b2184887a6653916d8c14959453b7f5757b866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Wed, 1 Sep 2021 11:19:02 -0400 Subject: [PATCH 4/6] chore: table style tests --- packages/babel-types/test/retrievers.js | 33 ++++++++++++++----------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/packages/babel-types/test/retrievers.js b/packages/babel-types/test/retrievers.js index 73d972571522..a66c0891c6c4 100644 --- a/packages/babel-types/test/retrievers.js +++ b/packages/babel-types/test/retrievers.js @@ -7,20 +7,25 @@ function getBody(program) { describe("retrievers", function () { describe("getBindingIdentifiers", function () { - it("variable declarations", function () { - const program = "var a = 1; let b = 2; const c = 3;"; - const ids = t.getBindingIdentifiers(getBody(program)); - expect(Object.keys(ids)).toEqual(["a", "b", "c"]); - }); - it("function declarations", function () { - const program = "var foo = 1; function bar() { var baz = 2; }"; - const ids = t.getBindingIdentifiers(getBody(program)); - expect(Object.keys(ids)).toEqual(["bar", "foo"]); - }); - it("export named declarations", function () { - const program = "export const foo = 'foo';"; - const ids = t.getBindingIdentifiers(getBody(program)); - expect(Object.keys(ids)).toEqual(["foo"]); + it.each([ + [ + "variable declarations", + getBody("var a = 1; let b = 2; const c = 3;"), + ["a", "b", "c"], + ], + [ + "function declarations", + getBody("var foo = 1; function bar() { var baz = 2; }"), + ["bar", "foo"], + ], + [ + "export named declarations", + getBody("export const foo = 'foo';"), + ["foo"], + ], + ])("%s", (_, program, bindingNames) => { + const ids = t.getBindingIdentifiers(program); + expect(Object.keys(ids)).toEqual(bindingNames); }); }); }); From b53b1e7f34e72d83e427c01611a107380cb63ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Wed, 1 Sep 2021 14:04:36 -0400 Subject: [PATCH 5/6] add more test cases --- packages/babel-types/test/retrievers.js | 48 +++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/packages/babel-types/test/retrievers.js b/packages/babel-types/test/retrievers.js index a66c0891c6c4..41ee709fb27b 100644 --- a/packages/babel-types/test/retrievers.js +++ b/packages/babel-types/test/retrievers.js @@ -18,11 +18,59 @@ describe("retrievers", function () { getBody("var foo = 1; function bar() { var baz = 2; }"), ["bar", "foo"], ], + [ + "object methods", + getBody("({ a(b) { let c } })")[0].expression.properties[0], + ["b"], + ], + [ + "class methods", + getBody("(class { a(b) { let c } })")[0].expression.body.body, + ["b"], + ], + [ + "class private methods", + getBody("(class { #a(b) { let c } })")[0].expression.body.body, + ["b"], + ], [ "export named declarations", getBody("export const foo = 'foo';"), ["foo"], ], + [ + "export default class declarations", + getBody("export default class foo {}"), + ["foo"], + ], + [ + "export default referenced identifiers", + getBody("export default foo"), + [], + ], + ["export all declarations", getBody("export * from 'x'"), []], + [ + "export all as namespace declarations", + getBody("export * as ns from 'x'"), + [], // exported bindings are not associated with declarations + ], + [ + "export namespace specifiers", + getBody("export * as ns from 'x'")[0].specifiers, + ["ns"], + ], + [ + "object patterns", + getBody("const { a, b: { ...c } = { d } } = {}"), + ["a", "c"], + ], + [ + "array patterns", + getBody("var [ a, ...{ b, ...c } ] = {}"), + ["a", "b", "c"], + ], + ["update expression", getBody("++x")[0].expression, ["x"]], + ["assignment expression", getBody("x ??= 1")[0].expression, ["x"]], ])("%s", (_, program, bindingNames) => { const ids = t.getBindingIdentifiers(program); expect(Object.keys(ids)).toEqual(bindingNames); From 5bfc350c9c5c034591116d77d6b6f2c872bb992d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Wed, 1 Sep 2021 14:05:08 -0400 Subject: [PATCH 6/6] fix: return params for private methods --- packages/babel-types/src/retrievers/getBindingIdentifiers.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/babel-types/src/retrievers/getBindingIdentifiers.ts b/packages/babel-types/src/retrievers/getBindingIdentifiers.ts index 8fe3500dbc89..81b5a9ce1ad0 100644 --- a/packages/babel-types/src/retrievers/getBindingIdentifiers.ts +++ b/packages/babel-types/src/retrievers/getBindingIdentifiers.ts @@ -121,6 +121,7 @@ getBindingIdentifiers.keys = { ArrowFunctionExpression: ["params"], ObjectMethod: ["params"], ClassMethod: ["params"], + ClassPrivateMethod: ["params"], ForInStatement: ["left"], ForOfStatement: ["left"],