From 44096a7e69567565ec1856ced1b20b9e64115262 Mon Sep 17 00:00:00 2001 From: Pavel Bocharov Date: Fri, 22 Oct 2021 11:56:39 +0300 Subject: [PATCH] Skip private members with decorators --- README.md | 1 + src/properties-minifier.ts | 7 ++++- tests/functional-test-cases.ts | 1 + .../private-with-decorators/input.ts | 17 +++++++++++ .../private-with-decorators/output.js | 29 +++++++++++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 tests/test-cases/private-with-decorators/input.ts create mode 100644 tests/test-cases/private-with-decorators/output.js diff --git a/README.md b/README.md index a189a4c..c3b309f 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ A TypeScript custom transformer which minify names of private class members. For now it just renames private members with prepending some prefix to name. For example, if you have `privateMember`, then after transformation the name will be `_private_privateMember`. After that you can use terser/uglify with mangle options to minify that members. +Note, that private class members with decorators won't be prefixed and further minified. ## Caution!!! diff --git a/src/properties-minifier.ts b/src/properties-minifier.ts index bb1bd7c..34cccb1 100644 --- a/src/properties-minifier.ts +++ b/src/properties-minifier.ts @@ -190,6 +190,11 @@ function isPrivateNonStaticClassMember(symbol: ts.Symbol | undefined): boolean { } return symbol.declarations.some((x: ts.Declaration) => { - return (isClassMember(x) || isConstructorParameter(x)) && isPrivateNonStatic(x); + // terser / uglify property minifiers aren't able to handle decorators + return (isClassMember(x) && !hasDecorators(x) || isConstructorParameter(x)) && isPrivateNonStatic(x); }); } + +function hasDecorators(node: ts.Node): boolean { + return !!node.decorators; +} diff --git a/tests/functional-test-cases.ts b/tests/functional-test-cases.ts index c48aa01..ed7ebd9 100644 --- a/tests/functional-test-cases.ts +++ b/tests/functional-test-cases.ts @@ -75,6 +75,7 @@ describe('Functional tests', () => { rootNames: [testCase.inputFileName], options: { target: ts.ScriptTarget.ES5, + experimentalDecorators: true, }, }); diff --git a/tests/test-cases/private-with-decorators/input.ts b/tests/test-cases/private-with-decorators/input.ts new file mode 100644 index 0000000..35b5189 --- /dev/null +++ b/tests/test-cases/private-with-decorators/input.ts @@ -0,0 +1,17 @@ +export class Class { + public publicField: number = 123; + //@ts-ignore + @decorator private privateField: string = 'string-value'; + + public constructor() { + this.privateMethod(this.privateField); + this.privateMethod(this.publicField); + + this['privateMethod'](this.privateField); + } + + //@ts-ignore + @decorator private privateMethod(a: string | number): void { } +} + +function decorator(target: any, propertyKey: string): void {} diff --git a/tests/test-cases/private-with-decorators/output.js b/tests/test-cases/private-with-decorators/output.js new file mode 100644 index 0000000..88b2d55 --- /dev/null +++ b/tests/test-cases/private-with-decorators/output.js @@ -0,0 +1,29 @@ +"use strict"; +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; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var Class = /** @class */ (function () { + function Class() { + this.publicField = 123; + //@ts-ignore + this.privateField = 'string-value'; + this.privateMethod(this.privateField); + this.privateMethod(this.publicField); + this['privateMethod'](this.privateField); + } + //@ts-ignore + Class.prototype.privateMethod = function (a) { }; + __decorate([ + decorator + ], Class.prototype, "privateField", void 0); + __decorate([ + decorator + ], Class.prototype, "privateMethod", null); + return Class; +}()); +exports.Class = Class; +function decorator(target, propertyKey) { }