Skip to content

Commit dda3d27

Browse files
clydindgp1130
authored andcommitted
refactor(@angular-devkit/build-angular): remove babel core runtime imports from elide-angular-metadata build optimizer pass
The `elide-angular-metadata` build optimization pass have been cleaned up and restructured to remove the need for a direct runtime dependency on `@babel/core`.
1 parent b9ec9ee commit dda3d27

File tree

1 file changed

+42
-34
lines changed

1 file changed

+42
-34
lines changed

packages/angular_devkit/build_angular/src/tools/babel/plugins/elide-angular-metadata.ts

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import { NodePath, PluginObj, types } from '@babel/core';
9+
import type { NodePath, PluginObj } from '@babel/core';
1010

1111
/**
1212
* The name of the Angular class metadata function created by the Angular compiler.
@@ -30,9 +30,19 @@ const SET_CLASS_DEBUG_INFO_NAME = 'ɵsetClassDebugInfo';
3030
* @returns An a string iterable containing one or more keywords.
3131
*/
3232
export function getKeywords(): Iterable<string> {
33-
return [SET_CLASS_METADATA_NAME, SET_CLASS_METADATA_ASYNC_NAME, SET_CLASS_DEBUG_INFO_NAME];
33+
return Object.keys(angularMetadataFunctions);
3434
}
3535

36+
/**
37+
* An object map of function names and related value checks for discovery of Angular generated
38+
* metadata calls.
39+
*/
40+
const angularMetadataFunctions: Record<string, (args: NodePath[]) => boolean> = {
41+
[SET_CLASS_METADATA_NAME]: isSetClassMetadataCall,
42+
[SET_CLASS_METADATA_ASYNC_NAME]: isSetClassMetadataAsyncCall,
43+
[SET_CLASS_DEBUG_INFO_NAME]: isSetClassDebugInfoCall,
44+
};
45+
3646
/**
3747
* A babel plugin factory function for eliding the Angular class metadata function (`ɵsetClassMetadata`).
3848
*
@@ -41,23 +51,27 @@ export function getKeywords(): Iterable<string> {
4151
export default function (): PluginObj {
4252
return {
4353
visitor: {
44-
CallExpression(path: NodePath<types.CallExpression>) {
45-
const callee = path.node.callee;
46-
const callArguments = path.node.arguments;
54+
CallExpression(path) {
55+
const callee = path.get('callee');
4756

4857
// The function being called must be the metadata function name
4958
let calleeName;
50-
if (types.isMemberExpression(callee) && types.isIdentifier(callee.property)) {
51-
calleeName = callee.property.name;
52-
} else if (types.isIdentifier(callee)) {
53-
calleeName = callee.name;
59+
if (callee.isMemberExpression()) {
60+
const calleeProperty = callee.get('property');
61+
if (calleeProperty.isIdentifier()) {
62+
calleeName = calleeProperty.node.name;
63+
}
64+
} else if (callee.isIdentifier()) {
65+
calleeName = callee.node.name;
66+
}
67+
68+
if (!calleeName) {
69+
return;
5470
}
5571

5672
if (
57-
calleeName !== undefined &&
58-
(isRemoveClassMetadataCall(calleeName, callArguments) ||
59-
isRemoveClassmetadataAsyncCall(calleeName, callArguments) ||
60-
isSetClassDebugInfoCall(calleeName, callArguments))
73+
Object.hasOwn(angularMetadataFunctions, calleeName) &&
74+
angularMetadataFunctions[calleeName](path.get('arguments'))
6175
) {
6276
// The metadata function is always emitted inside a function expression
6377
const parent = path.getFunctionParent();
@@ -74,47 +88,41 @@ export default function (): PluginObj {
7488
}
7589

7690
/** Determines if a function call is a call to `setClassMetadata`. */
77-
function isRemoveClassMetadataCall(name: string, args: types.CallExpression['arguments']): boolean {
91+
function isSetClassMetadataCall(callArguments: NodePath[]): boolean {
7892
// `setClassMetadata` calls have to meet the following criteria:
7993
// * First must be an identifier
8094
// * Second must be an array literal
8195
return (
82-
name === SET_CLASS_METADATA_NAME &&
83-
args.length === 4 &&
84-
types.isIdentifier(args[0]) &&
85-
types.isArrayExpression(args[1])
96+
callArguments.length === 4 &&
97+
callArguments[0].isIdentifier() &&
98+
callArguments[1].isArrayExpression()
8699
);
87100
}
88101

89102
/** Determines if a function call is a call to `setClassMetadataAsync`. */
90-
function isRemoveClassmetadataAsyncCall(
91-
name: string,
92-
args: types.CallExpression['arguments'],
93-
): boolean {
103+
function isSetClassMetadataAsyncCall(callArguments: NodePath[]): boolean {
94104
// `setClassMetadataAsync` calls have to meet the following criteria:
95105
// * First argument must be an identifier.
96106
// * Second argument must be an inline function.
97107
// * Third argument must be an inline function.
98108
return (
99-
name === SET_CLASS_METADATA_ASYNC_NAME &&
100-
args.length === 3 &&
101-
types.isIdentifier(args[0]) &&
102-
isInlineFunction(args[1]) &&
103-
isInlineFunction(args[2])
109+
callArguments.length === 3 &&
110+
callArguments[0].isIdentifier() &&
111+
isInlineFunction(callArguments[1]) &&
112+
isInlineFunction(callArguments[2])
104113
);
105114
}
106115

107116
/** Determines if a function call is a call to `setClassDebugInfo`. */
108-
function isSetClassDebugInfoCall(name: string, args: types.CallExpression['arguments']): boolean {
117+
function isSetClassDebugInfoCall(callArguments: NodePath[]): boolean {
109118
return (
110-
name === SET_CLASS_DEBUG_INFO_NAME &&
111-
args.length === 2 &&
112-
types.isIdentifier(args[0]) &&
113-
types.isObjectExpression(args[1])
119+
callArguments.length === 2 &&
120+
callArguments[0].isIdentifier() &&
121+
callArguments[1].isObjectExpression()
114122
);
115123
}
116124

117125
/** Determines if a node is an inline function expression. */
118-
function isInlineFunction(node: types.Node): boolean {
119-
return types.isFunctionExpression(node) || types.isArrowFunctionExpression(node);
126+
function isInlineFunction(path: NodePath): boolean {
127+
return path.isFunctionExpression() || path.isArrowFunctionExpression();
120128
}

0 commit comments

Comments
 (0)