Skip to content

Commit 6aaf8eb

Browse files
alan-agius4mgechev
authored andcommitted
fix(@angular-devkit/build-optimizer): replace multiple tslib helpers (#15400)
Inlined tslib helpers can be suffixed with `$` and a number when having multiple helpers in the same file. With this change we will replace all tslib inline helpers to imports from `tslib`
1 parent e642b53 commit 6aaf8eb

File tree

2 files changed

+70
-7
lines changed

2 files changed

+70
-7
lines changed

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

+16-7
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { isHelperName } from '../helpers/ast-utils';
1212
* @deprecated From 0.9.0
1313
*/
1414
export function testImportTslib(content: string) {
15-
const regex = /var (__extends|__decorate|__metadata|__param) = \(.*\r?\n\s+(.*\r?\n)*\s*\};/;
15+
const regex = /var (__extends|__decorate|__metadata|__param)(\$\d+)? = \(.*\r?\n\s+(.*\r?\n)*\s*\};/;
1616

1717
return regex.test(content);
1818
}
@@ -34,11 +34,18 @@ export function getImportTslibTransformer(): ts.TransformerFactory<ts.SourceFile
3434
const declarations = node.declarationList.declarations;
3535

3636
if (declarations.length === 1 && ts.isIdentifier(declarations[0].name)) {
37-
const name = (declarations[0].name as ts.Identifier).text;
37+
const name = declarations[0].name.text;
3838

39-
if (isHelperName(name)) {
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)) {
4046
// TODO: maybe add a few more checks, like checking the first part of the assignment.
41-
const tslibImport = createTslibImport(name, useRequire);
47+
const alias = name === helperName ? undefined : name;
48+
const tslibImport = createTslibImport(helperName, alias, useRequire);
4249
tslibImports.push(tslibImport);
4350

4451
return undefined;
@@ -66,6 +73,7 @@ export function getImportTslibTransformer(): ts.TransformerFactory<ts.SourceFile
6673

6774
function createTslibImport(
6875
name: string,
76+
aliases?: string,
6977
useRequire = false,
7078
): ts.VariableStatement | ts.ImportDeclaration {
7179
if (useRequire) {
@@ -75,14 +83,15 @@ function createTslibImport(
7583
const pureRequireCall = ts.addSyntheticLeadingComment(
7684
requireCall, ts.SyntaxKind.MultiLineCommentTrivia, '@__PURE__', false);
7785
const helperAccess = ts.createPropertyAccess(pureRequireCall, name);
78-
const variableDeclaration = ts.createVariableDeclaration(name, undefined, helperAccess);
86+
const variableDeclaration = ts.createVariableDeclaration(aliases || name, undefined, helperAccess);
7987
const variableStatement = ts.createVariableStatement(undefined, [variableDeclaration]);
8088

8189
return variableStatement;
8290
} else {
8391
// Use `import { __helper } from "tslib"`.
84-
const namedImports = ts.createNamedImports([ts.createImportSpecifier(undefined,
85-
ts.createIdentifier(name))]);
92+
const namedImports = ts.createNamedImports([
93+
ts.createImportSpecifier(aliases ? ts.createIdentifier(name) : undefined, ts.createIdentifier(aliases || name)),
94+
]);
8695
const importClause = ts.createImportClause(undefined, namedImports);
8796
const newNode = ts.createImportDeclaration(undefined, undefined, importClause,
8897
ts.createLiteral('tslib'));

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

+54
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,60 @@ describe('import-tslib', () => {
6868
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
6969
});
7070

71+
it('replaces multiple __decorate', () => {
72+
// tslint:disable:max-line-length
73+
const input = tags.stripIndent`
74+
var __decorate$1 = (this && this.__decorate) || function (decorators, target, key, desc) {
75+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
76+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
77+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
78+
return c > 3 && r && Object.defineProperty(target, key, r), r;
79+
};
80+
var __decorate$2 = (this && this.__decorate) || function (decorators, target, key, desc) {
81+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
82+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
83+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
84+
return c > 3 && r && Object.defineProperty(target, key, r), r;
85+
};
86+
`;
87+
const output = tags.stripIndent`
88+
import { __decorate as __decorate$1 } from "tslib";
89+
import { __decorate as __decorate$2 } from "tslib";
90+
`;
91+
92+
expect(testImportTslib(input)).toBeTruthy();
93+
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
94+
});
95+
96+
it('replaces multiple __decorate in CJS modules', () => {
97+
// tslint:disable:max-line-length
98+
const input = tags.stripIndent`
99+
var __decorate$1 = (this && this.__decorate) || function (decorators, target, key, desc) {
100+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
101+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
102+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
103+
return c > 3 && r && Object.defineProperty(target, key, r), r;
104+
};
105+
var __decorate$2 = (this && this.__decorate) || function (decorators, target, key, desc) {
106+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
107+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
108+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
109+
return c > 3 && r && Object.defineProperty(target, key, r), r;
110+
};
111+
112+
exports.meaning = 42;
113+
`;
114+
const output = tags.stripIndent`
115+
var __decorate$1 = /*@__PURE__*/ require("tslib").__decorate;
116+
var __decorate$2 = /*@__PURE__*/ require("tslib").__decorate;
117+
118+
exports.meaning = 42;
119+
`;
120+
121+
expect(testImportTslib(input)).toBeTruthy();
122+
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
123+
});
124+
71125
it('replaces __metadata', () => {
72126
const input = tags.stripIndent`
73127
var __metadata = (this && this.__metadata) || function (k, v) {

0 commit comments

Comments
 (0)