Skip to content

Commit 4df025f

Browse files
alan-agius4mgechev
authored andcommitted
fix(@angular-devkit/build-optimizer): don't mark tslib helpers which are suffixed with $ and a number as pure (#15451)
Closes #15392
1 parent 578b196 commit 4df025f

File tree

4 files changed

+64
-11
lines changed

4 files changed

+64
-11
lines changed

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

+39-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ describe('build-optimizer', () => {
100100
expect(boOutput.emitSkipped).toEqual(false);
101101
});
102102

103-
it(`doesn't add pure comments to tslib helpers`, () => {
103+
it('should not add pure comments to tslib helpers', () => {
104104
const input = tags.stripIndent`
105105
class LanguageState {
106106
}
@@ -138,6 +138,44 @@ describe('build-optimizer', () => {
138138
expect(boOutput.emitSkipped).toEqual(false);
139139
});
140140

141+
it('should not add pure comments to tslib helpers with $ and number suffix', () => {
142+
const input = tags.stripIndent`
143+
class LanguageState {
144+
}
145+
146+
LanguageState.ctorParameters = () => [
147+
{ type: TranslateService },
148+
{ type: undefined, decorators: [{ type: Inject, args: [LANGUAGE_CONFIG,] }] }
149+
];
150+
151+
__decorate$1([
152+
Action(CheckLanguage),
153+
__metadata("design:type", Function),
154+
__metadata("design:paramtypes", [Object]),
155+
__metadata("design:returntype", void 0)
156+
], LanguageState.prototype, "checkLanguage", null);
157+
`;
158+
159+
const output = tags.oneLine`
160+
let LanguageState = /*@__PURE__*/ (() => {
161+
class LanguageState {
162+
}
163+
164+
__decorate$1([
165+
Action(CheckLanguage),
166+
__metadata("design:type", Function),
167+
__metadata("design:paramtypes", [Object]),
168+
__metadata("design:returntype", void 0)
169+
], LanguageState.prototype, "checkLanguage", null);
170+
return LanguageState;
171+
})();
172+
`;
173+
174+
const boOutput = buildOptimizer({ content: input, isSideEffectFree: true });
175+
expect(tags.oneLine`${boOutput.content}`).toEqual(output);
176+
expect(boOutput.emitSkipped).toEqual(false);
177+
});
178+
141179
it('should not wrap classes which had all static properties dropped in IIFE', () => {
142180
const classDeclaration = tags.oneLine`
143181
import { Injectable } from '@angular/core';

packages/angular_devkit/build_optimizer/src/helpers/ast-utils.ts

+20
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,23 @@ export function hasPureComment(node: ts.Node): boolean {
5050
export function isHelperName(name: string): boolean {
5151
return tslibHelpers.has(name);
5252
}
53+
54+
/**
55+
* In FESM's when not using `importHelpers` there might be multiple in the same file.
56+
@example
57+
```
58+
var __decorate$1 = '';
59+
var __decorate$2 = '';
60+
```
61+
* @returns Helper name without the '$' and number suffix or `undefined` if it's not a helper.
62+
*/
63+
export function getCleanHelperName(name: string): string | undefined {
64+
const parts = name.split('$');
65+
const cleanName = parts[0];
66+
67+
if (parts.length > 2 || (parts.length === 2 && isNaN(+parts[1]))) {
68+
return undefined;
69+
}
70+
71+
return isHelperName(cleanName) ? cleanName : undefined;
72+
}

packages/angular_devkit/build_optimizer/src/transforms/import-tslib.ts

+3-8
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
import * as ts from 'typescript';
9-
import { isHelperName } from '../helpers/ast-utils';
9+
import { getCleanHelperName } from '../helpers/ast-utils';
1010

1111
/**
1212
* @deprecated From 0.9.0
@@ -35,14 +35,9 @@ export function getImportTslibTransformer(): ts.TransformerFactory<ts.SourceFile
3535

3636
if (declarations.length === 1 && ts.isIdentifier(declarations[0].name)) {
3737
const name = declarations[0].name.text;
38+
const helperName = getCleanHelperName(name);
3839

39-
// In FESM's when not using importHelpers there might be nultiple in the same file.
40-
// Example:
41-
// var __decorate$1 = '';
42-
// var __decorate$2 = '';
43-
const helperName = name.split(/\$\d+$/)[0];
44-
45-
if (isHelperName(helperName)) {
40+
if (helperName) {
4641
// TODO: maybe add a few more checks, like checking the first part of the assignment.
4742
const alias = name === helperName ? undefined : name;
4843
const tslibImport = createTslibImport(helperName, alias, useRequire);

packages/angular_devkit/build_optimizer/src/transforms/prefix-functions.ts

+2-2
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
import * as ts from 'typescript';
9-
import { addPureComment, hasPureComment, isHelperName } from '../helpers/ast-utils';
9+
import { addPureComment, getCleanHelperName, hasPureComment } from '../helpers/ast-utils';
1010

1111
export function getPrefixFunctionsTransformer(): ts.TransformerFactory<ts.SourceFile> {
1212
return (context: ts.TransformationContext): ts.Transformer<ts.SourceFile> => {
@@ -77,7 +77,7 @@ export function findTopLevelFunctions(parentNode: ts.Node): Set<ts.Node> {
7777
} else if (ts.isCallExpression(innerNode)) {
7878
let expression: ts.Expression = innerNode.expression;
7979

80-
if (ts.isIdentifier(expression) && isHelperName(expression.text)) {
80+
if (ts.isIdentifier(expression) && getCleanHelperName(expression.text)) {
8181
return;
8282
}
8383

0 commit comments

Comments
 (0)