babel / babel
Showing 4 of 34 files from the diff.
Other files ignored by Codecov

@@ -1,16 +1,24 @@
Loading
1 1
import { types as t } from "@babel/core";
2 2
import {
3 3
  pushPrivateName,
4 -
  buildPrivateNamesNodes,
5 4
  buildPrivateInstanceFieldInitSpec,
6 5
  buildPrivateStaticFieldInitSpec,
7 6
  buildPrivateInstanceMethodInitSpec,
8 -
  buildPrivateMethodDeclaration,
9 7
  transformPrivateNamesUsage,
10 8
} from "../utils/private";
11 9
import { buildPublicFieldInitSpec } from "../utils/public";
12 -
import { injectInitialization } from "../utils/misc";
13 -
import { replaceSupers, replaceThisContext } from "../utils/context";
10 +
import {
11 +
  injectInitialization,
12 +
  injectPureStatics,
13 +
  injectStaticInitialization,
14 +
} from "../utils/misc";
15 +
import {
16 +
  ensureClassRef,
17 +
  ensureExternalClassRef,
18 +
  replaceInnerBindingReferences,
19 +
  replaceSupers,
20 +
  replaceThisContextInExtractedNodes,
21 +
} from "../utils/context";
14 22
15 23
export default function classElementsToES6(api) {
16 24
  const constantSuper = api.assumption("constantSuper");
@@ -21,46 +29,6 @@
Loading
21 29
    Class(path, state) {
22 30
      const privateNamesMap = new Map();
23 31
24 -
      const initInstanceFields = nodes =>
25 -
        nodes.map(node => {
26 -
          if (t.isPrivate(node)) {
27 -
            return buildPrivateInstanceFieldInitSpec(
28 -
              t.thisExpression(),
29 -
              node,
30 -
              path.scope,
31 -
              privateNamesMap,
32 -
            );
33 -
          } else {
34 -
            return buildPublicFieldInitSpec(t.thisExpression(), node, state);
35 -
          }
36 -
        });
37 -
      const initStaticFields = nodes =>
38 -
        nodes
39 -
          .map(node => {
40 -
            if (t.isPrivate(node)) {
41 -
              return buildPrivateStaticFieldInitSpec(
42 -
                node,
43 -
                path.scope,
44 -
                privateNamesMap,
45 -
              );
46 -
            } else {
47 -
              return buildPublicFieldInitSpec(classRef, node, state);
48 -
            }
49 -
          })
50 -
          .filter(Boolean);
51 -
      const initPrivMethods = nodes =>
52 -
        nodes
53 -
          .map(node =>
54 -
            buildPrivateInstanceMethodInitSpec(
55 -
              t.thisExpression(),
56 -
              node,
57 -
              path.scope,
58 -
              privateNamesMap,
59 -
              state,
60 -
            ),
61 -
          )
62 -
          .filter(Boolean);
63 -
64 32
      const eltsToRemove = [];
65 33
      const instanceFields = [];
66 34
      const staticFields = [];
@@ -68,6 +36,16 @@
Loading
68 36
      const staticPrivMethods = [];
69 37
      let constructorPath;
70 38
39 +
      const { classRef, originalClassRef } = ensureClassRef(path);
40 +
      let needsClassRef = false;
41 +
      let externalClassRef;
42 +
      const getExternalClassRef = () =>
43 +
        (externalClassRef ||= ensureExternalClassRef(
44 +
          path,
45 +
          classRef,
46 +
          originalClassRef,
47 +
        ));
48 +
71 49
      for (const el of path.get("body.body")) {
72 50
        const isStatic = el.node.static;
73 51
        if (el.isPrivate()) {
@@ -82,7 +60,15 @@
Loading
82 60
83 61
        if (el.isClassPrivateMethod()) {
84 62
          (isStatic ? staticPrivMethods : instancePrivMethods).push(el.node);
63 +
85 64
          replaceSupers(path, el, state, constantSuper);
65 +
          needsClassRef =
66 +
            replaceInnerBindingReferences(
67 +
              el,
68 +
              getExternalClassRef(),
69 +
              classRef,
70 +
            ) || needsClassRef;
71 +
86 72
          eltsToRemove.push(el);
87 73
          continue;
88 74
        }
@@ -92,20 +78,6 @@
Loading
92 78
        }
93 79
      }
94 80
95 -
      let classRef = path.node.id;
96 -
      if (!classRef) {
97 -
        path.set("id", (classRef = path.scope.generateUidIdentifier("class")));
98 -
      }
99 -
100 -
      const stmtParent = path.find(
101 -
        parent =>
102 -
          parent.isStatement() ||
103 -
          parent.isDeclaration() ||
104 -
          parent.parentPath.isArrowFunctionExpression({
105 -
            body: parent.node,
106 -
          }),
107 -
      );
108 -
109 81
      transformPrivateNamesUsage(
110 82
        classRef,
111 83
        path,
@@ -114,20 +86,61 @@
Loading
114 86
        state,
115 87
      );
116 88
117 -
      for (let i = 0, j = 0; i < staticFields.length; i++) {
118 -
        while (staticFields[i] !== eltsToRemove[j].node) {
119 -
          j++;
120 -
          if (j > eltsToRemove.length) throw new Error("Internal Babel error");
121 -
        }
122 -
123 -
        replaceThisContext(
89 +
      needsClassRef =
90 +
        replaceThisContextInExtractedNodes(
91 +
          staticFields,
92 +
          eltsToRemove,
124 93
          path,
125 -
          eltsToRemove[j],
126 -
          classRef,
94 +
          getExternalClassRef(),
95 +
          originalClassRef,
127 96
          state,
128 97
          constantSuper,
129 -
        );
130 -
      }
98 +
        ) || needsClassRef;
99 +
100 +
      const initInstanceFields = nodes =>
101 +
        nodes.map(node => {
102 +
          if (t.isPrivate(node)) {
103 +
            return buildPrivateInstanceFieldInitSpec(
104 +
              t.thisExpression(),
105 +
              node,
106 +
              path.scope,
107 +
              privateNamesMap,
108 +
            );
109 +
          } else {
110 +
            return buildPublicFieldInitSpec(t.thisExpression(), node, state);
111 +
          }
112 +
        });
113 +
      const initStaticFields = nodes =>
114 +
        nodes
115 +
          .map(node => {
116 +
            if (t.isPrivate(node)) {
117 +
              return buildPrivateStaticFieldInitSpec(
118 +
                node,
119 +
                path.scope,
120 +
                privateNamesMap,
121 +
              );
122 +
            } else {
123 +
              needsClassRef = true;
124 +
              return buildPublicFieldInitSpec(
125 +
                getExternalClassRef(),
126 +
                node,
127 +
                state,
128 +
              );
129 +
            }
130 +
          })
131 +
          .filter(Boolean);
132 +
      const initPrivMethods = nodes =>
133 +
        nodes
134 +
          .map(node =>
135 +
            buildPrivateInstanceMethodInitSpec(
136 +
              t.thisExpression(),
137 +
              node,
138 +
              path.scope,
139 +
              privateNamesMap,
140 +
              state,
141 +
            ),
142 +
          )
143 +
          .filter(Boolean);
131 144
132 145
      const instanceInit = [
133 146
        ...initPrivMethods(instancePrivMethods),
@@ -141,30 +154,21 @@
Loading
141 154
        );
142 155
      }
143 156
144 -
      const pureStaticNodesBefore = buildPrivateNamesNodes(
157 +
      injectPureStatics({
158 +
        state,
159 +
        path,
145 160
        privateNamesMap,
161 +
        instancePrivMethods,
162 +
        staticPrivMethods,
146 163
        privateFieldsAsProperties,
147 -
        state,
148 -
      );
149 -
      if (pureStaticNodesBefore) stmtParent.insertBefore(pureStaticNodesBefore);
150 -
151 -
      const pureStaticNodesAfter = instancePrivMethods
152 -
        .concat(staticPrivMethods)
153 -
        .map(method =>
154 -
          buildPrivateMethodDeclaration(
155 -
            method,
156 -
            privateNamesMap,
157 -
            privateFieldsAsProperties,
158 -
          ),
159 -
        );
160 -
      if (pureStaticNodesAfter.length > 0) {
161 -
        stmtParent.insertAfter(pureStaticNodesAfter);
162 -
      }
164 +
      });
163 165
164 -
      const staticNodesAfter = initStaticFields(staticFields).map(n =>
165 -
        t.expressionStatement(n),
166 +
      injectStaticInitialization(
167 +
        path,
168 +
        initStaticFields(staticFields).map(n => t.expressionStatement(n)),
169 +
        getExternalClassRef(),
170 +
        needsClassRef,
166 171
      );
167 -
      if (staticNodesAfter.length > 0) path.insertAfter(staticNodesAfter);
168 172
169 173
      eltsToRemove.forEach(el => el.remove());
170 174
    },

@@ -1,5 +1,9 @@
Loading
1 1
import { template, types as t } from "@babel/core";
2 2
import { findBareSupers } from "./context";
3 +
import {
4 +
  buildPrivateMethodDeclaration,
5 +
  buildPrivateNamesNodes,
6 +
} from "./private";
3 7
4 8
const referenceVisitor = {
5 9
  "TSTypeAnnotation|TypeAnnotation"(path) {
@@ -55,3 +59,69 @@
Loading
55 59
    constructor.get("body").unshiftContainer("body", nodes);
56 60
  }
57 61
}
62 +
63 +
export function injectStaticInitialization(
64 +
  path,
65 +
  nodes,
66 +
  externalClassRef,
67 +
  needsClassRef,
68 +
) {
69 +
  if (path.isClassDeclaration()) {
70 +
    path.insertAfter(nodes);
71 +
  } else {
72 +
    const assignment = t.assignmentExpression(
73 +
      "=",
74 +
      t.cloneNode(externalClassRef),
75 +
      path.node,
76 +
    );
77 +
    if (nodes.length > 0) {
78 +
      path.replaceWithMultiple([
79 +
        assignment,
80 +
        ...nodes,
81 +
        t.cloneNode(externalClassRef),
82 +
      ]);
83 +
      path.scope.push({ id: externalClassRef });
84 +
    } else if (needsClassRef) {
85 +
      path.replaceWith(assignment);
86 +
      path.scope.push({ id: externalClassRef });
87 +
    }
88 +
  }
89 +
}
90 +
91 +
export function injectPureStatics({
92 +
  state,
93 +
  path,
94 +
  privateNamesMap,
95 +
  instancePrivMethods,
96 +
  staticPrivMethods,
97 +
  privateFieldsAsProperties,
98 +
}) {
99 +
  const stmtParent = path.find(
100 +
    parent =>
101 +
      parent.isStatement() ||
102 +
      parent.isDeclaration() ||
103 +
      parent.parentPath.isArrowFunctionExpression({
104 +
        body: parent.node,
105 +
      }),
106 +
  );
107 +
108 +
  const pureStaticNodesBefore = buildPrivateNamesNodes(
109 +
    privateNamesMap,
110 +
    privateFieldsAsProperties,
111 +
    state,
112 +
  );
113 +
  if (pureStaticNodesBefore) stmtParent.insertBefore(pureStaticNodesBefore);
114 +
115 +
  const pureStaticNodesAfter = instancePrivMethods
116 +
    .concat(staticPrivMethods)
117 +
    .map(method =>
118 +
      buildPrivateMethodDeclaration(
119 +
        method,
120 +
        privateNamesMap,
121 +
        privateFieldsAsProperties,
122 +
      ),
123 +
    );
124 +
  if (pureStaticNodesAfter.length > 0) {
125 +
    stmtParent.insertAfter(pureStaticNodesAfter);
126 +
  }
127 +
}

@@ -1,15 +1,23 @@
Loading
1 1
import { types as t } from "@babel/core";
2 2
import {
3 3
  pushPrivateName,
4 -
  buildPrivateNamesNodes,
5 4
  buildPrivateInstanceFieldInitSpec,
6 5
  buildPrivateStaticFieldInitSpec,
7 6
  buildPrivateInstanceMethodInitSpec,
8 -
  buildPrivateMethodDeclaration,
9 7
  transformPrivateNamesUsage,
10 8
} from "../utils/private";
11 -
import { injectInitialization } from "../utils/misc";
12 -
import { replaceSupers, replaceThisContext } from "../utils/context";
9 +
import {
10 +
  injectInitialization,
11 +
  injectPureStatics,
12 +
  injectStaticInitialization,
13 +
} from "../utils/misc";
14 +
import {
15 +
  ensureClassRef,
16 +
  ensureExternalClassRef,
17 +
  replaceInnerBindingReferences,
18 +
  replaceSupers,
19 +
  replaceThisContextInExtractedNodes,
20 +
} from "../utils/context";
13 21
14 22
function unshiftFieldInit(fieldPath, exprs) {
15 23
  if (exprs.length === 0) return;
@@ -82,6 +90,16 @@
Loading
82 90
      const eltsToRemove = [];
83 91
      let constructorPath;
84 92
93 +
      const { classRef, originalClassRef } = ensureClassRef(path);
94 +
      let needsClassRef = false;
95 +
      let externalClassRef;
96 +
      const getExternalClassRef = () =>
97 +
        (externalClassRef ||= ensureExternalClassRef(
98 +
          path,
99 +
          classRef,
100 +
          originalClassRef,
101 +
        ));
102 +
85 103
      for (const el of path.get("body.body")) {
86 104
        if (el.isPrivate()) {
87 105
          pushPrivateName(privateNamesMap, el);
@@ -97,7 +115,15 @@
Loading
97 115
98 116
        if (el.isClassPrivateMethod()) {
99 117
          meta.privMethods.push(el.node);
118 +
100 119
          replaceSupers(path, el, state, constantSuper);
120 +
          needsClassRef =
121 +
            replaceInnerBindingReferences(
122 +
              el,
123 +
              getExternalClassRef(),
124 +
              classRef,
125 +
            ) || needsClassRef;
126 +
101 127
          eltsToRemove.push(el);
102 128
          continue;
103 129
        }
@@ -119,11 +145,6 @@
Loading
119 145
        }
120 146
      }
121 147
122 -
      let classRef = path.node.id;
123 -
      if (!classRef) {
124 -
        path.set("id", (classRef = path.scope.generateUidIdentifier("class")));
125 -
      }
126 -
127 148
      transformPrivateNamesUsage(
128 149
        classRef,
129 150
        path,
@@ -162,45 +183,32 @@
Loading
162 183
        );
163 184
      }
164 185
165 -
      const staticNodesBefore = buildPrivateNamesNodes(
186 +
      injectPureStatics({
187 +
        state,
188 +
        path,
166 189
        privateNamesMap,
190 +
        instancePrivMethods: instanceMeta.privMethods,
191 +
        staticPrivMethods: staticMeta.privMethods,
167 192
        privateFieldsAsProperties,
168 -
        state,
169 -
      );
170 -
      if (staticNodesBefore) path.insertBefore(staticNodesBefore);
171 -
172 -
      for (let i = 0, j = 0; i < staticMeta.privFields.length; i++) {
173 -
        while (staticMeta.privFields[i] !== eltsToRemove[j].node) {
174 -
          j++;
175 -
          if (j > eltsToRemove.length) throw new Error("Internal Babel error");
176 -
        }
193 +
      });
177 194
178 -
        replaceThisContext(
195 +
      needsClassRef =
196 +
        replaceThisContextInExtractedNodes(
197 +
          staticMeta.privFields,
198 +
          eltsToRemove,
179 199
          path,
180 -
          eltsToRemove[j],
181 -
          classRef,
200 +
          getExternalClassRef(),
201 +
          originalClassRef,
182 202
          state,
183 203
          constantSuper,
184 -
        );
185 -
      }
204 +
        ) || needsClassRef;
186 205
187 -
      const staticNodesAfter = [
188 -
        ...initStaticPrivFields(staticMeta.privFields),
189 -
        ...instanceMeta.privMethods
190 -
          .concat(staticMeta.privMethods)
191 -
          .map(method =>
192 -
            buildPrivateMethodDeclaration(
193 -
              method,
194 -
              privateNamesMap,
195 -
              privateFieldsAsProperties,
196 -
            ),
197 -
          ),
198 -
      ];
199 -
      if (staticNodesAfter.length > 0) {
200 -
        path
201 -
          .find(parent => parent.isStatement() || parent.isDeclaration())
202 -
          .insertAfter(staticNodesAfter);
203 -
      }
206 +
      injectStaticInitialization(
207 +
        path,
208 +
        initStaticPrivFields(staticMeta.privFields),
209 +
        getExternalClassRef(),
210 +
        needsClassRef,
211 +
      );
204 212
205 213
      eltsToRemove.forEach(el => el.remove());
206 214
    },

@@ -3,18 +3,89 @@
Loading
3 3
  environmentVisitor,
4 4
} from "@babel/helper-replace-supers";
5 5
6 +
export function ensureClassRef(path) {
7 +
  const originalClassRef = path.node.id;
8 +
  let classRef = originalClassRef;
9 +
  if (!classRef) {
10 +
    path.set("id", (classRef = path.scope.generateUidIdentifier("class")));
11 +
  }
12 +
13 +
  return { classRef, originalClassRef };
14 +
}
15 +
16 +
export function ensureExternalClassRef(path, classRef, originalClassRef) {
17 +
  if (path.isClassDeclaration()) {
18 +
    return classRef;
19 +
  } else {
20 +
    return originalClassRef === classRef
21 +
      ? path.scope.generateUidIdentifier(classRef.name)
22 +
      : // If the classRef has been generated by us, it's already an UUID and we
23 +
        // don't need a new id.
24 +
        classRef;
25 +
  }
26 +
}
27 +
28 +
export function replaceThisContextInExtractedNodes(
29 +
  nodes,
30 +
  extractedPaths,
31 +
  path,
32 +
  externalClassRef,
33 +
  originalClassRef,
34 +
  state,
35 +
  constantSuper,
36 +
) {
37 +
  let needsClassRef = false;
38 +
39 +
  for (let i = 0, j = 0; i < nodes.length; i++) {
40 +
    while (nodes[i] !== extractedPaths[j].node) {
41 +
      j++;
42 +
      if (j > extractedPaths.length) {
43 +
        throw new Error("Internal Babel error");
44 +
      }
45 +
    }
46 +
47 +
    needsClassRef =
48 +
      replaceThisContext(
49 +
        path,
50 +
        extractedPaths[j],
51 +
        externalClassRef,
52 +
        state,
53 +
        constantSuper,
54 +
        originalClassRef,
55 +
      ) || needsClassRef;
56 +
  }
57 +
58 +
  return needsClassRef;
59 +
}
60 +
6 61
export function replaceThisContext(
7 62
  classPath,
8 63
  fieldPath,
9 64
  ref,
10 65
  file,
11 66
  constantSuper,
67 +
  innerBindingRef,
12 68
) {
13 69
  replaceSupers(classPath, fieldPath, file, constantSuper);
14 70
15 71
  const state = { classRef: ref, needsClassRef: false };
16 72
  fieldPath.traverse(thisContextVisitor, state);
17 73
74 +
  return (
75 +
    replaceInnerBindingReferences(fieldPath, ref, innerBindingRef) ||
76 +
    state.needsClassRef
77 +
  );
78 +
}
79 +
80 +
export function replaceInnerBindingReferences(
81 +
  elemPath,
82 +
  outerBindingRef,
83 +
  innerBindingRef,
84 +
) {
85 +
  const state = { needsClassRef: false, outerBindingRef, innerBindingRef };
86 +
  if (outerBindingRef.name !== innerBindingRef?.name) {
87 +
    elemPath.traverse(innerReferencesVisitor, state);
88 +
  }
18 89
  return state.needsClassRef;
19 90
}
20 91
@@ -51,6 +122,17 @@
Loading
51 122
  environmentVisitor,
52 123
]);
53 124
125 +
const innerReferencesVisitor = {
126 +
  ReferencedIdentifier(path, state) {
127 +
    if (
128 +
      path.scope.bindingIdentifierEquals(path.node.name, state.innerBindingRef)
129 +
    ) {
130 +
      state.needsClassRef = true;
131 +
      path.node.name = state.outerBindingRef.name;
132 +
    }
133 +
  },
134 +
};
135 +
54 136
export const findBareSupers = traverse.visitors.merge([
55 137
  {
56 138
    Super(path) {
Files Coverage
codemods 100.00%
eslint 93.14%
packages 91.99%
Project Totals (464 files) 92.04%
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