MCPcopy Create free account
hub / github.com/babel/babel / transform

Function transform

packages/babel-plugin-transform-optional-chaining/src/transform.ts:240–301  ·  view source on GitHub ↗
(
  path: NodePath<t.OptionalCallExpression | t.OptionalMemberExpression>,
  assumptions: OptionalChainAssumptions,
)

Source from the content-addressed store, hash-verified

238}
239
240export function transform(
241 path: NodePath<t.OptionalCallExpression | t.OptionalMemberExpression>,
242 assumptions: OptionalChainAssumptions,
243) {
244 const { scope } = path;
245
246 // maybeWrapped points to the outermost transparent expression wrapper
247 // or the path itself
248 const maybeWrapped = findOutermostTransparentParent(path);
249 const { parentPath } = maybeWrapped;
250
251 if (parentPath.isUnaryExpression({ operator: "delete" })) {
252 transformOptionalChain(
253 path,
254 assumptions,
255 parentPath,
256 t.booleanLiteral(true),
257 );
258 } else {
259 let wrapLast: ((value: t.Expression) => t.Expression) | undefined;
260 if (
261 parentPath.isCallExpression({ callee: maybeWrapped.node }) &&
262 // note that the first condition must implies that `path.optional` is `true`,
263 // otherwise the parentPath should be an OptionalCallExpression
264 path.isOptionalMemberExpression()
265 ) {
266 // Ensure (a?.b)() has proper `this`
267 wrapLast = ((replacement: t.MemberExpression) => {
268 // `(a?.b)()` to `(a == null ? undefined : a.b.bind(a))()`
269 // object must not be Super as super?.foo is invalid
270
271 const object = skipTransparentExprWrapperNodes(
272 replacement.object,
273 ) as t.Expression;
274 let baseRef: t.Expression | undefined;
275 if (!assumptions.pureGetters || !isSimpleMemberExpression(object)) {
276 // memoize the context object when getters are not always pure
277 // or the object is not a simple member expression
278 // `(a?.b.c)()` to `(a == null ? undefined : (_a$b = a.b).c.bind(_a$b))()`
279 baseRef = scope.maybeGenerateMemoised(object)!;
280 if (baseRef) {
281 replacement.object = t.assignmentExpression("=", baseRef, object);
282 }
283 }
284 return t.callExpression(
285 t.memberExpression(replacement, t.identifier("bind")),
286 [t.cloneNode(baseRef ?? object)],
287 );
288 }) as (value: t.Expression) => t.Expression;
289 }
290
291 transformOptionalChain(
292 path,
293 assumptions,
294 path,
295 willPathCastToBoolean(maybeWrapped)
296 ? t.booleanLiteral(false)
297 : t.buildUndefinedNode(),

Calls 9

willPathCastToBooleanFunction · 0.90
transformOptionalChainFunction · 0.85
isSimpleMemberExpressionFunction · 0.85
isUnaryExpressionMethod · 0.80
isCallExpressionMethod · 0.80
maybeGenerateMemoisedMethod · 0.80

Tested by

no test coverage detected