babel / babel

@@ -26,7 +26,9 @@
Loading
26 26
  unaryExpression,
27 27
} from "@babel/types";
28 28
import type * as t from "@babel/types";
29 +
import environmentVisitor from "@babel/helper-environment-visitor";
29 30
import nameFunction from "@babel/helper-function-name";
31 +
import { merge as mergeVisitors } from "../visitors";
30 32
import type NodePath from "./index";
31 33
32 34
export function toComputedKey(this: NodePath) {
@@ -190,6 +192,18 @@
Loading
190 192
  }
191 193
}
192 194
195 +
const getSuperCallsVisitor = mergeVisitors<{
196 +
  allSuperCalls: NodePath<t.CallExpression>[];
197 +
}>([
198 +
  {
199 +
    CallExpression(child, { allSuperCalls }) {
200 +
      if (!child.get("callee").isSuper()) return;
201 +
      allSuperCalls.push(child);
202 +
    },
203 +
  },
204 +
  environmentVisitor,
205 +
]);
206 +
193 207
/**
194 208
 * Given a function, traverse its contents, and if there are references to "this", "arguments", "super",
195 209
 * or "new.target", ensure that these references reference the parent environment around this function.
@@ -252,20 +266,8 @@
Loading
252 266
        "Unable to handle nested super() usage in arrow",
253 267
      );
254 268
    }
255 -
    const allSuperCalls = [];
256 -
    thisEnvFn.traverse({
257 -
      Function(child) {
258 -
        if (child.isArrowFunctionExpression()) return;
259 -
        child.skip();
260 -
      },
261 -
      ClassProperty(child) {
262 -
        child.skip();
263 -
      },
264 -
      CallExpression(child) {
265 -
        if (!child.get("callee").isSuper()) return;
266 -
        allSuperCalls.push(child);
267 -
      },
268 -
    });
269 +
    const allSuperCalls: NodePath<t.CallExpression>[] = [];
270 +
    thisEnvFn.traverse(getSuperCallsVisitor, { allSuperCalls });
269 271
    const superBinding = getSuperBinding(thisEnvFn);
270 272
    allSuperCalls.forEach(superCall => {
271 273
      const callee = identifier(superBinding);
@@ -508,34 +510,33 @@
Loading
508 510
  );
509 511
}
510 512
513 +
const assignSuperThisVisitor = mergeVisitors<{
514 +
  supers: WeakSet<t.CallExpression>;
515 +
  thisBinding: string;
516 +
}>([
517 +
  {
518 +
    CallExpression(child, { supers, thisBinding }) {
519 +
      if (!child.get("callee").isSuper()) return;
520 +
      if (supers.has(child.node)) return;
521 +
      supers.add(child.node);
522 +
523 +
      child.replaceWithMultiple([
524 +
        child.node,
525 +
        assignmentExpression("=", identifier(thisBinding), identifier("this")),
526 +
      ]);
527 +
    },
528 +
  },
529 +
  environmentVisitor,
530 +
]);
531 +
511 532
// Create a binding that evaluates to the "this" of the given function.
512 533
function getThisBinding(thisEnvFn, inConstructor) {
513 534
  return getBinding(thisEnvFn, "this", thisBinding => {
514 535
    if (!inConstructor || !hasSuperClass(thisEnvFn)) return thisExpression();
515 536
516 -
    const supers = new WeakSet();
517 -
    thisEnvFn.traverse({
518 -
      Function(child) {
519 -
        if (child.isArrowFunctionExpression()) return;
520 -
        child.skip();
521 -
      },
522 -
      ClassProperty(child) {
523 -
        child.skip();
524 -
      },
525 -
      CallExpression(child) {
526 -
        if (!child.get("callee").isSuper()) return;
527 -
        if (supers.has(child.node)) return;
528 -
        supers.add(child.node);
529 -
530 -
        child.replaceWithMultiple([
531 -
          child.node,
532 -
          assignmentExpression(
533 -
            "=",
534 -
            identifier(thisBinding),
535 -
            identifier("this"),
536 -
          ),
537 -
        ]);
538 -
      },
537 +
    thisEnvFn.traverse(assignSuperThisVisitor, {
538 +
      supers: new WeakSet(),
539 +
      thisBinding,
539 540
    });
540 541
  });
541 542
}
@@ -601,25 +602,18 @@
Loading
601 602
  return data;
602 603
}
603 604
604 -
function getScopeInformation(fnPath) {
605 -
  const thisPaths = [];
606 -
  const argumentsPaths = [];
607 -
  const newTargetPaths = [];
608 -
  const superProps = [];
609 -
  const superCalls = [];
610 -
611 -
  fnPath.traverse({
612 -
    ClassProperty(child) {
613 -
      child.skip();
614 -
    },
615 -
    Function(child) {
616 -
      if (child.isArrowFunctionExpression()) return;
617 -
      child.skip();
618 -
    },
619 -
    ThisExpression(child) {
605 +
const getScopeInformationVisitor = mergeVisitors<{
606 +
  thisPaths: NodePath<t.ThisExpression | t.JSXIdentifier>[];
607 +
  superCalls: NodePath<t.CallExpression>[];
608 +
  superProps: NodePath<t.MemberExpression>[];
609 +
  argumentsPaths: NodePath<t.Identifier | t.JSXIdentifier>[];
610 +
  newTargetPaths: NodePath<t.MetaProperty>[];
611 +
}>([
612 +
  {
613 +
    ThisExpression(child, { thisPaths }) {
620 614
      thisPaths.push(child);
621 615
    },
622 -
    JSXIdentifier(child) {
616 +
    JSXIdentifier(child, { thisPaths }) {
623 617
      if (child.node.name !== "this") return;
624 618
      if (
625 619
        !child.parentPath.isJSXMemberExpression({ object: child.node }) &&
@@ -630,14 +624,14 @@
Loading
630 624
631 625
      thisPaths.push(child);
632 626
    },
633 -
    CallExpression(child) {
627 +
    CallExpression(child, { superCalls }) {
634 628
      if (child.get("callee").isSuper()) superCalls.push(child);
635 629
    },
636 -
    MemberExpression(child) {
630 +
    MemberExpression(child, { superProps }) {
637 631
      if (child.get("object").isSuper()) superProps.push(child);
638 632
    },
639 -
    ReferencedIdentifier(child) {
640 -
      if (child.node.name !== "arguments") return;
633 +
    Identifier(child, { argumentsPaths }) {
634 +
      if (!child.isReferencedIdentifier({ name: "arguments" })) return;
641 635
642 636
      let curr = child.scope;
643 637
      do {
@@ -652,12 +646,29 @@
Loading
652 646
653 647
      argumentsPaths.push(child);
654 648
    },
655 -
    MetaProperty(child) {
649 +
    MetaProperty(child, { newTargetPaths }) {
656 650
      if (!child.get("meta").isIdentifier({ name: "new" })) return;
657 651
      if (!child.get("property").isIdentifier({ name: "target" })) return;
658 652
659 653
      newTargetPaths.push(child);
660 654
    },
655 +
  },
656 +
  environmentVisitor,
657 +
]);
658 +
659 +
function getScopeInformation(fnPath) {
660 +
  const thisPaths = [];
661 +
  const argumentsPaths = [];
662 +
  const newTargetPaths = [];
663 +
  const superProps = [];
664 +
  const superCalls = [];
665 +
666 +
  fnPath.traverse(getScopeInformationVisitor, {
667 +
    thisPaths,
668 +
    argumentsPaths,
669 +
    newTargetPaths,
670 +
    superProps,
671 +
    superCalls,
661 672
  });
662 673
663 674
  return {

@@ -1,5 +1,6 @@
Loading
1 1
import * as virtualTypes from "./path/lib/virtual-types";
2 2
import { DEPRECATED_KEYS, FLIPPED_ALIAS_KEYS, TYPES } from "@babel/types";
3 +
import type { Visitor } from "./types";
3 4
4 5
/**
5 6
 * explode() will take a visitor object with all of the various shorthands
@@ -175,6 +176,12 @@
Loading
175 176
  }
176 177
}
177 178
179 +
export function merge<State>(visitors: Visitor<State>[]): Visitor<State>;
180 +
export function merge(
181 +
  visitors: Visitor<unknown>[],
182 +
  states?: any[],
183 +
  wrapper?: Function | null,
184 +
): Visitor<unknown>;
178 185
export function merge(
179 186
  visitors: any[],
180 187
  states: any[] = [],

@@ -1,8 +1,7 @@
Loading
1 1
import type { NodePath, Visitor } from "@babel/traverse";
2 2
import nameFunction from "@babel/helper-function-name";
3 -
import ReplaceSupers, {
4 -
  environmentVisitor,
5 -
} from "@babel/helper-replace-supers";
3 +
import ReplaceSupers from "@babel/helper-replace-supers";
4 +
import environmentVisitor from "@babel/helper-environment-visitor";
6 5
import optimiseCall from "@babel/helper-optimise-call-expression";
7 6
import { traverse, template, types as t } from "@babel/core";
8 7
import annotateAsPure from "@babel/helper-annotate-as-pure";

@@ -538,7 +538,7 @@
Loading
538 538
  handle(
539 539
    this: HandlerState<State> & State,
540 540
    member: Member,
541 -
    noDocumentAll: boolean,
541 +
    noDocumentAll?: boolean,
542 542
  ): void;
543 543
  memoiser: AssignmentMemoiser;
544 544
}

@@ -0,0 +1,38 @@
Loading
1 +
import type { NodePath } from "@babel/traverse";
2 +
import { VISITOR_KEYS, staticBlock } from "@babel/types";
3 +
import type * as t from "@babel/types";
4 +
5 +
// TODO (Babel 8): Don't export this function.
6 +
export function skipAllButComputedKey(
7 +
  path: NodePath<t.Method | t.ClassProperty>,
8 +
) {
9 +
  // If the path isn't computed, just skip everything.
10 +
  if (!path.node.computed) {
11 +
    path.skip();
12 +
    return;
13 +
  }
14 +
15 +
  // So it's got a computed key. Make sure to skip every other key the
16 +
  // traversal would visit.
17 +
  const keys = VISITOR_KEYS[path.type];
18 +
  for (const key of keys) {
19 +
    if (key !== "key") path.skipKey(key);
20 +
  }
21 +
}
22 +
23 +
// Methods are handled by the Method visitor; arrows are not skipped because they inherit the context.
24 +
const skipKey = process.env.BABEL_8_BREAKING
25 +
  ? "StaticBlock|ClassPrivateProperty|TypeAnnotation|FunctionDeclaration|FunctionExpression"
26 +
  : (staticBlock ? "StaticBlock|" : "") +
27 +
    "ClassPrivateProperty|TypeAnnotation|FunctionDeclaration|FunctionExpression";
28 +
29 +
// environmentVisitor should be used when traversing the whole class and not for specific class elements/methods.
30 +
// For perf reasons, the environmentVisitor might be traversed with `{ noScope: true }`, which means `path.scope` is undefined.
31 +
// Avoid using `path.scope` here
32 +
export default {
33 +
  [skipKey]: path => path.skip(),
34 +
35 +
  "Method|ClassProperty"(path: NodePath<t.Method | t.ClassProperty>) {
36 +
    skipAllButComputedKey(path);
37 +
  },
38 +
};

@@ -1,4 +1,4 @@
Loading
1 -
import { environmentVisitor } from "@babel/helper-replace-supers";
1 +
import environmentVisitor from "@babel/helper-environment-visitor";
2 2
import traverse from "@babel/traverse";
3 3
import { numericLiteral, unaryExpression } from "@babel/types";
4 4
import type * as t from "@babel/types";

@@ -1,9 +1,10 @@
Loading
1 1
import type { HubInterface, NodePath, Scope } from "@babel/traverse";
2 2
import traverse from "@babel/traverse";
3 3
import memberExpressionToFunctions from "@babel/helper-member-expression-to-functions";
4 +
import type { HandlerState } from "@babel/helper-member-expression-to-functions";
4 5
import optimiseCall from "@babel/helper-optimise-call-expression";
6 +
import environmentVisitor from "@babel/helper-environment-visitor";
5 7
import {
6 -
  VISITOR_KEYS,
7 8
  assignmentExpression,
8 9
  booleanLiteral,
9 10
  callExpression,
@@ -11,12 +12,17 @@
Loading
11 12
  identifier,
12 13
  memberExpression,
13 14
  sequenceExpression,
14 -
  staticBlock,
15 15
  stringLiteral,
16 16
  thisExpression,
17 17
} from "@babel/types";
18 18
import type * as t from "@babel/types";
19 19
20 +
// TODO (Babel 8): Don't export this.
21 +
export {
22 +
  default as environmentVisitor,
23 +
  skipAllButComputedKey,
24 +
} from "@babel/helper-environment-visitor";
25 +
20 26
/**
21 27
 * Creates an expression which result is the proto of objectRef.
22 28
 *
@@ -38,49 +44,9 @@
Loading
38 44
  return callExpression(file.addHelper("getPrototypeOf"), [targetRef]);
39 45
}
40 46
41 -
export function skipAllButComputedKey(
42 -
  path: NodePath<t.Method | t.ClassProperty | t.ClassPrivateProperty>,
43 -
) {
44 -
  // If the path isn't computed, just skip everything.
45 -
  // @ts-expect-error todo(flow->ts) check node type before cheking the property
46 -
  if (!path.node.computed) {
47 -
    path.skip();
48 -
    return;
49 -
  }
50 -
51 -
  // So it's got a computed key. Make sure to skip every other key the
52 -
  // traversal would visit.
53 -
  const keys = VISITOR_KEYS[path.type];
54 -
  for (const key of keys) {
55 -
    if (key !== "key") path.skipKey(key);
56 -
  }
57 -
}
58 -
59 -
// environmentVisitor should be used when traversing the whole class and not for specific class elements/methods.
60 -
// For perf reasons, the environmentVisitor will be traversed with `{ noScope: true }`, which means `path.scope` is undefined.
61 -
// Avoid using `path.scope` here
62 -
export const environmentVisitor = {
63 -
  // todo (Babel 8): remove StaticBlock brand checks
64 -
  [`${staticBlock ? "StaticBlock|" : ""}ClassPrivateProperty|TypeAnnotation`](
65 -
    path: NodePath,
66 -
  ) {
67 -
    path.skip();
68 -
  },
69 -
70 -
  Function(path: NodePath) {
71 -
    // Methods will be handled by the Method visit
72 -
    if (path.isMethod()) return;
73 -
    // Arrow functions inherit their parent's environment
74 -
    if (path.isArrowFunctionExpression()) return;
75 -
    path.skip();
76 -
  },
77 -
78 -
  "Method|ClassProperty"(path: NodePath<t.Method | t.ClassProperty>) {
79 -
    skipAllButComputedKey(path);
80 -
  },
81 -
};
82 -
83 -
const visitor = traverse.visitors.merge([
47 +
const visitor = traverse.visitors.merge<
48 +
  HandlerState<ReplaceState> & ReplaceState
49 +
>([
84 50
  environmentVisitor,
85 51
  {
86 52
    Super(path, state) {

@@ -1,9 +1,8 @@
Loading
1 1
import { template, traverse, types as t } from "@babel/core";
2 2
import type { File } from "@babel/core";
3 3
import type { NodePath, Visitor, Scope } from "@babel/traverse";
4 -
import ReplaceSupers, {
5 -
  environmentVisitor,
6 -
} from "@babel/helper-replace-supers";
4 +
import ReplaceSupers from "@babel/helper-replace-supers";
5 +
import environmentVisitor from "@babel/helper-environment-visitor";
7 6
import memberExpressionToFunctions from "@babel/helper-member-expression-to-functions";
8 7
import type {
9 8
  Handler,
@@ -851,7 +850,11 @@
Loading
851 850
  );
852 851
}
853 852
854 -
const thisContextVisitor = traverse.visitors.merge([
853 +
const thisContextVisitor = traverse.visitors.merge<{
854 +
  classRef: t.Identifier;
855 +
  needsClassRef: boolean;
856 +
  innerBinding: t.Identifier;
857 +
}>([
855 858
  {
856 859
    ThisExpression(path, state) {
857 860
      state.needsClassRef = true;

@@ -1,9 +1,9 @@
Loading
1 1
import { template, traverse, types as t } from "@babel/core";
2 2
import type { File } from "@babel/core";
3 3
import type { NodePath, Scope, Visitor, Binding } from "@babel/traverse";
4 -
import { environmentVisitor } from "@babel/helper-replace-supers";
4 +
import environmentVisitor from "@babel/helper-environment-visitor";
5 5
6 -
const findBareSupers = traverse.visitors.merge([
6 +
const findBareSupers = traverse.visitors.merge<NodePath<t.CallExpression>[]>([
7 7
  {
8 8
    Super(path: NodePath<t.Super>) {
9 9
      const { node, parentPath } = path;
Files Coverage
codemods 100.00%
eslint 94.95%
packages 90.89%
Project Totals (462 files) 91.02%
1
coverage:
2
  parsers:
3
    javascript:
4
      enable_partials: yes
5
  status:
6
    project:
7
      default:
8
        target: "90%"
9
    patch:
10
      enabled: false
11
ignore:
12
  - packages/babel-types/src/*/generated/*
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading