From 3a3259ad6141f1fcd68cf3567cef4902a0ffd080 Mon Sep 17 00:00:00 2001 From: Dan Bucholtz Date: Thu, 6 Apr 2017 15:28:42 -0500 Subject: [PATCH] fix(decorators): don't remove third party transpiled (not static) decorators --- src/optimization/decorators.spec.ts | 51 +++++++++++++++++++++++ src/optimization/decorators.ts | 64 +++++++++++++++++++---------- 2 files changed, 93 insertions(+), 22 deletions(-) diff --git a/src/optimization/decorators.spec.ts b/src/optimization/decorators.spec.ts index 4c35be5a..2cf582a7 100644 --- a/src/optimization/decorators.spec.ts +++ b/src/optimization/decorators.spec.ts @@ -1279,6 +1279,57 @@ var _a, _b; const result: string = magicString.toString(); expect(result.indexOf(injectableDecorator)).toBeGreaterThan(1); }); + + it('should not remove the third party decorators', () => { + + const selectDecorator = ` +__decorate([ + select(), + __metadata("design:type", Object) +], DashPage.prototype, "user$", void 0); +`; + + const knownContent = ` +var __decorate = (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 __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +import { Component } from '@angular/core'; +import { select } from '@angular-redux/store'; +var DashPage = (function () { + function DashPage() { + } + DashPage.prototype.ionViewDidLoad = function () { + var _this = this; + this.user$.subscribe(function (user) { + _this.user = user; + }); + }; + return DashPage; +}()); +${selectDecorator} +DashPage = __decorate([ + Component({ + selector: 'page-dash', + templateUrl: 'dash-page.html' + }), + __metadata("design:paramtypes", []) +], DashPage); +export { DashPage }; +//# sourceMappingURL=dash-page.js.map +`; + + let magicString = new MagicString(knownContent); + const filePath = join(ionicAngular, 'components', 'action-sheet', 'action-sheet-component.js'); + magicString = decorators.purgeTranspiledDecorators(filePath, knownContent, ionicAngular, angularDir, srcDir, magicString); + const result: string = magicString.toString(); + expect(result.indexOf(selectDecorator)).toBeGreaterThan(1); + }); }); describe('addPureAnnotation', () => { diff --git a/src/optimization/decorators.ts b/src/optimization/decorators.ts index 4018f18a..e092dd7b 100644 --- a/src/optimization/decorators.ts +++ b/src/optimization/decorators.ts @@ -68,32 +68,47 @@ function getTranspiledDecoratorExpressionStatements(sourceFile: SourceFile) { if (expressionStatement && expressionStatement.expression && expressionStatement.expression.kind === SyntaxKind.CallExpression && (expressionStatement.expression as CallExpression).expression - && ((expressionStatement.expression as CallExpression).expression as Identifier).text === '___decorate') { + && ((expressionStatement.expression as CallExpression).expression as Identifier).text === '___decorate' + && (expressionStatement.expression as CallExpression).arguments + && (expressionStatement.expression as CallExpression).arguments.length > 0 + && (expressionStatement.expression as CallExpression).arguments[0].kind === SyntaxKind.ArrayLiteralExpression + && ((expressionStatement.expression as CallExpression).arguments[0] as ArrayLiteralExpression).elements + && ((expressionStatement.expression as CallExpression).arguments[0] as ArrayLiteralExpression).elements.length > 0 + && (((expressionStatement.expression as CallExpression).arguments[0] as ArrayLiteralExpression).elements[0] as CallExpression).expression + && (((expressionStatement.expression as CallExpression).arguments[0] as ArrayLiteralExpression).elements[0] as CallExpression).expression.kind === SyntaxKind.Identifier + && canRemoveDecoratorNode(((((expressionStatement.expression as CallExpression).arguments[0] as ArrayLiteralExpression).elements[0] as CallExpression).expression as Identifier).text) + ) { toReturn.push(expressionStatement); } else if (expressionStatement && expressionStatement.expression - && expressionStatement.expression.kind === SyntaxKind.BinaryExpression - && (expressionStatement.expression as BinaryExpression).right - && (expressionStatement.expression as BinaryExpression).right.kind === SyntaxKind.CallExpression - && ((expressionStatement.expression as BinaryExpression).right as CallExpression).expression - && (((expressionStatement.expression as BinaryExpression).right as CallExpression).expression as Identifier).text === '___decorate') { - - ((expressionStatement.expression as BinaryExpression).right as CallExpression).arguments.forEach(argument => { - if (argument.kind === SyntaxKind.ArrayLiteralExpression) { - let injectableFound = false; - for (const element of (argument as ArrayLiteralExpression).elements) { - if (element.kind === SyntaxKind.CallExpression && (element as CallExpression).expression - && ((element as CallExpression).expression as Identifier).text === 'Injectable' ) { - injectableFound = true; - break; - } - } - if (!injectableFound) { - toReturn.push(expressionStatement); - } + && expressionStatement.expression.kind === SyntaxKind.BinaryExpression + && (expressionStatement.expression as BinaryExpression).right + && (expressionStatement.expression as BinaryExpression).right.kind === SyntaxKind.CallExpression + && ((expressionStatement.expression as BinaryExpression).right as CallExpression).expression + && (((expressionStatement.expression as BinaryExpression).right as CallExpression).expression as Identifier).text === '___decorate' + && ((expressionStatement.expression as BinaryExpression).right as CallExpression).arguments + && ((expressionStatement.expression as BinaryExpression).right as CallExpression).arguments.length > 0 + && ((expressionStatement.expression as BinaryExpression).right as CallExpression).arguments[0].kind === SyntaxKind.ArrayLiteralExpression + && (((expressionStatement.expression as BinaryExpression).right as CallExpression).arguments[0] as ArrayLiteralExpression).elements + && (((expressionStatement.expression as BinaryExpression).right as CallExpression).arguments[0] as ArrayLiteralExpression).elements.length > 0 ) { + + let immovableDecoratorFound = false; + + // remove the last item in the array as it is always __metadata() and should not be considered here + const numElements = (((expressionStatement.expression as BinaryExpression).right as CallExpression).arguments[0] as ArrayLiteralExpression).elements.length - 1; + const elementsToEvaluate = (((expressionStatement.expression as BinaryExpression).right as CallExpression).arguments[0] as ArrayLiteralExpression).elements.slice(0, numElements); + for (const element of elementsToEvaluate) { + if (element.kind === SyntaxKind.CallExpression && (element as CallExpression).expression + && !canRemoveDecoratorNode(((element as CallExpression).expression as Identifier).text)) { + + immovableDecoratorFound = true; + break; } - }); + } + if (!immovableDecoratorFound) { + toReturn.push(expressionStatement); + } } }); return toReturn; @@ -170,7 +185,9 @@ function getDecoratorsExpressionStatements(typescriptFile: SourceFile) { const expressionStatements = findNodes(typescriptFile, typescriptFile, SyntaxKind.ExpressionStatement, false) as ExpressionStatement[]; const decoratorExpressionStatements: ExpressionStatement[] = []; for (const expressionStatement of expressionStatements) { - if (expressionStatement.expression && (expressionStatement.expression as BinaryExpression).left && ((expressionStatement.expression as BinaryExpression).left as PropertyAccessExpression).name && ((expressionStatement.expression as BinaryExpression).left as PropertyAccessExpression).name.text === 'decorators') { + if (expressionStatement.expression && (expressionStatement.expression as BinaryExpression).left + && ((expressionStatement.expression as BinaryExpression).left as PropertyAccessExpression).name + && ((expressionStatement.expression as BinaryExpression).left as PropertyAccessExpression).name.text === 'decorators') { decoratorExpressionStatements.push(expressionStatement); } } @@ -248,6 +265,8 @@ function canRemoveDecoratorNode(decoratorType: string) { return true; } else if (decoratorType === VIEW_CHILDREN_DECORATOR) { return true; + } else if (decoratorType === IONIC_PAGE_DECORATOR) { + return true; } return false; } @@ -265,5 +284,6 @@ export const OUTPUT_DECORATOR = 'Output'; export const PIPE_DECORATOR = 'Pipe'; export const VIEW_CHILD_DECORATOR = 'ViewChild'; export const VIEW_CHILDREN_DECORATOR = 'ViewChildren'; +export const IONIC_PAGE_DECORATOR = 'IonicPage'; export const PURE_ANNOTATION = ' /*#__PURE__*/';