Skip to content

Commit

Permalink
fix(@angular-devkit/build-optimizer): replace multiple tslib helpers (#…
Browse files Browse the repository at this point in the history
…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`
  • Loading branch information
alan-agius4 authored and mgechev committed Aug 23, 2019
1 parent 2eae78c commit 59d80f5
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { isHelperName } from '../helpers/ast-utils';
* @deprecated From 0.9.0
*/
export function testImportTslib(content: string) {
const regex = /var (__extends|__decorate|__metadata|__param) = \(.*\r?\n\s+(.*\r?\n)*\s*\};/;
const regex = /var (__extends|__decorate|__metadata|__param)(\$\d+)? = \(.*\r?\n\s+(.*\r?\n)*\s*\};/;

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

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

if (isHelperName(name)) {
// In FESM's when not using importHelpers there might be nultiple in the same file.
// Example:
// var __decorate$1 = '';
// var __decorate$2 = '';
const helperName = name.split(/\$\d+$/)[0];

if (isHelperName(helperName)) {
// TODO: maybe add a few more checks, like checking the first part of the assignment.
const tslibImport = createTslibImport(name, useRequire);
const alias = name === helperName ? undefined : name;
const tslibImport = createTslibImport(helperName, alias, useRequire);
tslibImports.push(tslibImport);

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

function createTslibImport(
name: string,
aliases?: string,
useRequire = false,
): ts.VariableStatement | ts.ImportDeclaration {
if (useRequire) {
Expand All @@ -75,14 +83,15 @@ function createTslibImport(
const pureRequireCall = ts.addSyntheticLeadingComment(
requireCall, ts.SyntaxKind.MultiLineCommentTrivia, '@__PURE__', false);
const helperAccess = ts.createPropertyAccess(pureRequireCall, name);
const variableDeclaration = ts.createVariableDeclaration(name, undefined, helperAccess);
const variableDeclaration = ts.createVariableDeclaration(aliases || name, undefined, helperAccess);
const variableStatement = ts.createVariableStatement(undefined, [variableDeclaration]);

return variableStatement;
} else {
// Use `import { __helper } from "tslib"`.
const namedImports = ts.createNamedImports([ts.createImportSpecifier(undefined,
ts.createIdentifier(name))]);
const namedImports = ts.createNamedImports([
ts.createImportSpecifier(aliases ? ts.createIdentifier(name) : undefined, ts.createIdentifier(aliases || name)),
]);
const importClause = ts.createImportClause(undefined, namedImports);
const newNode = ts.createImportDeclaration(undefined, undefined, importClause,
ts.createLiteral('tslib'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,60 @@ describe('import-tslib', () => {
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});

it('replaces multiple __decorate', () => {
// tslint:disable:max-line-length
const input = tags.stripIndent`
var __decorate$1 = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __decorate$2 = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
`;
const output = tags.stripIndent`
import { __decorate as __decorate$1 } from "tslib";
import { __decorate as __decorate$2 } from "tslib";
`;

expect(testImportTslib(input)).toBeTruthy();
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});

it('replaces multiple __decorate in CJS modules', () => {
// tslint:disable:max-line-length
const input = tags.stripIndent`
var __decorate$1 = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __decorate$2 = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
exports.meaning = 42;
`;
const output = tags.stripIndent`
var __decorate$1 = /*@__PURE__*/ require("tslib").__decorate;
var __decorate$2 = /*@__PURE__*/ require("tslib").__decorate;
exports.meaning = 42;
`;

expect(testImportTslib(input)).toBeTruthy();
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});

it('replaces __metadata', () => {
const input = tags.stripIndent`
var __metadata = (this && this.__metadata) || function (k, v) {
Expand Down

0 comments on commit 59d80f5

Please sign in to comment.