@angular/build
Version:
Official build system for Angular
110 lines (109 loc) • 4.41 kB
JavaScript
;
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getKeywords = getKeywords;
exports.default = default_1;
/**
* The name of the Angular class metadata function created by the Angular compiler.
*/
const SET_CLASS_METADATA_NAME = 'ɵsetClassMetadata';
/**
* Name of the asynchronous Angular class metadata function created by the Angular compiler.
*/
const SET_CLASS_METADATA_ASYNC_NAME = 'ɵsetClassMetadataAsync';
/**
* Name of the function that sets debug information on classes.
*/
const SET_CLASS_DEBUG_INFO_NAME = 'ɵsetClassDebugInfo';
/**
* Provides one or more keywords that if found within the content of a source file indicate
* that this plugin should be used with a source file.
*
* @returns An a string iterable containing one or more keywords.
*/
function getKeywords() {
return Object.keys(angularMetadataFunctions);
}
/**
* An object map of function names and related value checks for discovery of Angular generated
* metadata calls.
*/
const angularMetadataFunctions = {
[SET_CLASS_METADATA_NAME]: isSetClassMetadataCall,
[SET_CLASS_METADATA_ASYNC_NAME]: isSetClassMetadataAsyncCall,
[SET_CLASS_DEBUG_INFO_NAME]: isSetClassDebugInfoCall,
};
/**
* A babel plugin factory function for eliding the Angular class metadata function (`ɵsetClassMetadata`).
*
* @returns A babel plugin object instance.
*/
function default_1() {
return {
visitor: {
CallExpression(path) {
const callee = path.get('callee');
// The function being called must be the metadata function name
let calleeName;
if (callee.isMemberExpression()) {
const calleeProperty = callee.get('property');
if (calleeProperty.isIdentifier()) {
calleeName = calleeProperty.node.name;
}
}
else if (callee.isIdentifier()) {
calleeName = callee.node.name;
}
if (!calleeName) {
return;
}
if (Object.hasOwn(angularMetadataFunctions, calleeName) &&
angularMetadataFunctions[calleeName](path.get('arguments'))) {
// The metadata function is always emitted inside a function expression
const parent = path.getFunctionParent();
if (parent && (parent.isFunctionExpression() || parent.isArrowFunctionExpression())) {
// Replace the metadata function with `void 0` which is the equivalent return value
// of the metadata function.
path.replaceWith(path.scope.buildUndefinedNode());
}
}
},
},
};
}
/** Determines if a function call is a call to `setClassMetadata`. */
function isSetClassMetadataCall(callArguments) {
// `setClassMetadata` calls have to meet the following criteria:
// * First must be an identifier
// * Second must be an array literal
return (callArguments.length === 4 &&
callArguments[0].isIdentifier() &&
callArguments[1].isArrayExpression());
}
/** Determines if a function call is a call to `setClassMetadataAsync`. */
function isSetClassMetadataAsyncCall(callArguments) {
// `setClassMetadataAsync` calls have to meet the following criteria:
// * First argument must be an identifier.
// * Second argument must be an inline function.
// * Third argument must be an inline function.
return (callArguments.length === 3 &&
callArguments[0].isIdentifier() &&
isInlineFunction(callArguments[1]) &&
isInlineFunction(callArguments[2]));
}
/** Determines if a function call is a call to `setClassDebugInfo`. */
function isSetClassDebugInfoCall(callArguments) {
return (callArguments.length === 2 &&
callArguments[0].isIdentifier() &&
callArguments[1].isObjectExpression());
}
/** Determines if a node is an inline function expression. */
function isInlineFunction(path) {
return path.isFunctionExpression() || path.isArrowFunctionExpression();
}