Skip to content
This repository was archived by the owner on Apr 4, 2025. It is now read-only.

Commit bc5a19a

Browse files
clydinfilipesilva
authored andcommitted
fix(@angular-devkit/build-optimizer): further improvements to enum validation
1 parent 49e8eee commit bc5a19a

File tree

5 files changed

+75
-59
lines changed

5 files changed

+75
-59
lines changed

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { getImportTslibTransformer, testImportTslib } from '../transforms/import
1616
import { getPrefixClassesTransformer, testPrefixClasses } from '../transforms/prefix-classes';
1717
import { getPrefixFunctionsTransformer } from '../transforms/prefix-functions';
1818
import { getScrubFileTransformer, testScrubFile } from '../transforms/scrub-file';
19-
import { getWrapEnumsTransformer, testWrapEnums } from '../transforms/wrap-enums';
19+
import { getWrapEnumsTransformer } from '../transforms/wrap-enums';
2020

2121

2222
// Angular packages are known to have no side effects.
@@ -140,9 +140,7 @@ export function buildOptimizer(options: BuildOptimizerOptions): TransformJavascr
140140
getTransforms.unshift(getImportTslibTransformer);
141141
}
142142

143-
if (testWrapEnums(content)) {
144-
getTransforms.unshift(getWrapEnumsTransformer);
145-
}
143+
getTransforms.unshift(getWrapEnumsTransformer);
146144

147145
const transformJavascriptOpts: TransformJavascriptOptions = {
148146
content: content,

packages/angular_devkit/build_optimizer/src/index.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,11 @@ export { getImportTslibTransformer, testImportTslib } from './transforms/import-
1818
export { getPrefixClassesTransformer, testPrefixClasses } from './transforms/prefix-classes';
1919
export { getPrefixFunctionsTransformer } from './transforms/prefix-functions';
2020
export { getScrubFileTransformer, testScrubFile } from './transforms/scrub-file';
21-
export { getWrapEnumsTransformer, testWrapEnums } from './transforms/wrap-enums';
21+
export { getWrapEnumsTransformer } from './transforms/wrap-enums';
22+
23+
/**
24+
* @deprecated since version 6.0
25+
*/
26+
export function testWrapEnums(_content: string) {
27+
return true;
28+
}

packages/angular_devkit/build_optimizer/src/transforms/wrap-enums.ts

+63-47
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,6 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
import * as ts from 'typescript';
9-
import { drilldownNodes } from '../helpers/ast-utils';
10-
11-
12-
export function testWrapEnums(content: string) {
13-
// TODO: remove this method, it's not doing anything anymore.
14-
return true;
15-
}
169

1710
function isBlockLike(node: ts.Node): node is ts.BlockLike {
1811
return node.kind === ts.SyntaxKind.Block
@@ -166,73 +159,96 @@ function visitBlockStatements(
166159

167160
// TS 2.3 enums have statements that are inside a IIFE.
168161
function findTs2_3EnumIife(name: string, statement: ts.Statement): ts.CallExpression | null {
169-
if (!ts.isExpressionStatement(statement) || !ts.isCallExpression(statement.expression)) {
162+
if (!ts.isExpressionStatement(statement)) {
163+
return null;
164+
}
165+
166+
let expression = statement.expression;
167+
while (ts.isParenthesizedExpression(expression)) {
168+
expression = expression.expression;
169+
}
170+
171+
if (!expression || !ts.isCallExpression(expression) || expression.arguments.length !== 1) {
172+
return null;
173+
}
174+
175+
const callExpression = expression;
176+
177+
const argument = expression.arguments[0];
178+
if (!ts.isBinaryExpression(argument)
179+
|| argument.operatorToken.kind !== ts.SyntaxKind.BarBarToken) {
180+
return null;
181+
}
182+
183+
if (!ts.isIdentifier(argument.left) || argument.left.text !== name) {
184+
return null;
185+
}
186+
187+
expression = expression.expression;
188+
while (ts.isParenthesizedExpression(expression)) {
189+
expression = expression.expression;
190+
}
191+
192+
if (!expression || !ts.isFunctionExpression(expression) || expression.parameters.length !== 1) {
170193
return null;
171194
}
172195

173-
const funcExpr = drilldownNodes<ts.FunctionExpression>(statement,
174-
[
175-
{ prop: null, kind: ts.SyntaxKind.ExpressionStatement },
176-
{ prop: 'expression', kind: ts.SyntaxKind.CallExpression },
177-
{ prop: 'expression', kind: ts.SyntaxKind.ParenthesizedExpression },
178-
{ prop: 'expression', kind: ts.SyntaxKind.FunctionExpression },
179-
]);
180-
181-
if (funcExpr === null) { return null; }
182-
183-
if (!(
184-
funcExpr.parameters.length === 1
185-
&& funcExpr.parameters[0].name.kind === ts.SyntaxKind.Identifier
186-
&& (funcExpr.parameters[0].name as ts.Identifier).text === name
187-
)) {
196+
const parameter = expression.parameters[0];
197+
if (!ts.isIdentifier(parameter.name) || parameter.name.text !== name) {
188198
return null;
189199
}
190200

191201
// In TS 2.3 enums, the IIFE contains only expressions with a certain format.
192202
// If we find any that is different, we ignore the whole thing.
193-
for (const innerStmt of funcExpr.body.statements) {
203+
for (let bodyIndex = 0; bodyIndex < expression.body.statements.length; ++bodyIndex) {
204+
const bodyStatement = expression.body.statements[bodyIndex];
194205

195-
const innerBinExpr = drilldownNodes<ts.BinaryExpression>(innerStmt,
196-
[
197-
{ prop: null, kind: ts.SyntaxKind.ExpressionStatement },
198-
{ prop: 'expression', kind: ts.SyntaxKind.BinaryExpression },
199-
]);
206+
if (!ts.isExpressionStatement(bodyStatement) || !bodyStatement.expression) {
207+
return null;
208+
}
200209

201-
if (innerBinExpr === null) { return null; }
210+
if (!ts.isBinaryExpression(bodyStatement.expression)
211+
|| bodyStatement.expression.operatorToken.kind !== ts.SyntaxKind.FirstAssignment) {
212+
return null;
213+
}
202214

203-
if (!(innerBinExpr.operatorToken.kind === ts.SyntaxKind.FirstAssignment
204-
&& innerBinExpr.left.kind === ts.SyntaxKind.ElementAccessExpression)) {
215+
const assignment = bodyStatement.expression.left;
216+
const value = bodyStatement.expression.right;
217+
if (!ts.isElementAccessExpression(assignment) || !ts.isStringLiteral(value)) {
205218
return null;
206219
}
207220

208-
const innerElemAcc = innerBinExpr.left as ts.ElementAccessExpression;
221+
if (!ts.isIdentifier(assignment.expression) || assignment.expression.text !== name) {
222+
return null;
223+
}
209224

210-
if (!(
211-
innerElemAcc.expression.kind === ts.SyntaxKind.Identifier
212-
&& (innerElemAcc.expression as ts.Identifier).text === name
213-
&& innerElemAcc.argumentExpression
214-
&& innerElemAcc.argumentExpression.kind === ts.SyntaxKind.BinaryExpression
215-
)) {
225+
const memberArgument = assignment.argumentExpression;
226+
if (!memberArgument || !ts.isBinaryExpression(memberArgument)
227+
|| memberArgument.operatorToken.kind !== ts.SyntaxKind.FirstAssignment) {
216228
return null;
217229
}
218230

219-
const innerArgBinExpr = innerElemAcc.argumentExpression as ts.BinaryExpression;
220231

221-
if (innerArgBinExpr.left.kind !== ts.SyntaxKind.ElementAccessExpression) {
232+
if (!ts.isElementAccessExpression(memberArgument.left)) {
233+
return null;
234+
}
235+
236+
if (!ts.isIdentifier(memberArgument.left.expression)
237+
|| memberArgument.left.expression.text !== name) {
222238
return null;
223239
}
224240

225-
const innerArgElemAcc = innerArgBinExpr.left as ts.ElementAccessExpression;
241+
if (!memberArgument.left.argumentExpression
242+
|| !ts.isStringLiteral(memberArgument.left.argumentExpression)) {
243+
return null;
244+
}
226245

227-
if (!(
228-
innerArgElemAcc.expression.kind === ts.SyntaxKind.Identifier
229-
&& (innerArgElemAcc.expression as ts.Identifier).text === name
230-
)) {
246+
if (memberArgument.left.argumentExpression.text !== value.text) {
231247
return null;
232248
}
233249
}
234250

235-
return statement.expression;
251+
return callExpression;
236252
}
237253

238254
// TS 2.2 enums have statements after the variable declaration, with index statements followed

packages/angular_devkit/build_optimizer/src/transforms/wrap-enums_spec.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// tslint:disable-next-line:no-implicit-dependencies
99
import { tags } from '@angular-devkit/core';
1010
import { transformJavascript } from '../helpers/transform-javascript';
11-
import { getWrapEnumsTransformer, testWrapEnums } from './wrap-enums';
11+
import { getWrapEnumsTransformer } from './wrap-enums';
1212

1313

1414
const transform = (content: string) => transformJavascript(
@@ -34,7 +34,6 @@ describe('wrap-enums', () => {
3434
}());
3535
`;
3636

37-
expect(testWrapEnums(input)).toBeTruthy();
3837
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
3938
});
4039

@@ -54,7 +53,6 @@ describe('wrap-enums', () => {
5453
})({});
5554
`;
5655

57-
expect(testWrapEnums(input)).toBeTruthy();
5856
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
5957
});
6058

@@ -78,7 +76,6 @@ describe('wrap-enums', () => {
7876
})({});
7977
`;
8078

81-
expect(testWrapEnums(input)).toBeTruthy();
8279
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
8380
});
8481

@@ -112,7 +109,6 @@ describe('wrap-enums', () => {
112109
}());
113110
`;
114111

115-
expect(testWrapEnums(input)).toBeTruthy();
116112
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
117113
});
118114

@@ -162,7 +158,6 @@ describe('wrap-enums', () => {
162158
})({});
163159
`;
164160

165-
expect(testWrapEnums(input)).toBeTruthy();
166161
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
167162
});
168163
});

0 commit comments

Comments
 (0)