fix(@angular-devkit/build-optimizer): wrap es2015 class expressions for better tree-shaking

ClassExpressions such as the below are not treeshakable unless we wrap them in an IIFE

```js
let AggregateColumnDirective = class AggregateColumnDirective {
	constructor(viewContainerRef) { }
};
AggregateColumnDirective = __decorate([
	Directive({}),
	__metadata("design:paramtypes", [ViewContainerRef])
], AggregateColumnDirective);
```

With this change we wrap the above in an IIFE and mark it as a PURE function.
```js
const AggregateColumnDirective = /*@__PURE__*/ (() => {
	let AggregateColumnDirective = class AggregateColumnDirective {
		constructor(viewContainerRef) { }
	};
	AggregateColumnDirective = __decorate([
		Directive({}),
		__metadata("design:paramtypes", [ViewContainerRef])
	], AggregateColumnDirective);

	return AggregateColumnDirective;
})();
```

With this pattern if the class is unused it will be dropped.

Note: In future we should rename `wrap-enums` to something more generic, and combine class-fold with this transformer especially considering the future fix that needs to be done for https://github.com/angular/angular-cli/issues/14610

Fixes #14577
This commit is contained in:
Alan Agius 2019-06-01 17:57:30 +02:00 committed by Alex Eagle
parent bebd8b6c09
commit f5200775f9
2 changed files with 479 additions and 254 deletions

View File

@ -61,7 +61,7 @@ function visitBlockStatements(
};
// 'oIndex' is the original statement index; 'uIndex' is the updated statement index
for (let oIndex = 0, uIndex = 0; oIndex < statements.length; oIndex++, uIndex++) {
for (let oIndex = 0, uIndex = 0; oIndex < statements.length - 1; oIndex++, uIndex++) {
const currentStatement = statements[oIndex];
// these can't contain an enum declaration
@ -74,9 +74,14 @@ function visitBlockStatements(
// * be a variable statement
// * have only one declaration
// * have an identifer as a declaration name
if (oIndex < statements.length - 1
&& ts.isVariableStatement(currentStatement)
&& currentStatement.declarationList.declarations.length === 1) {
// ClassExpression declarations must:
// * not be last statement
// * be a variable statement
// * have only one declaration
// * have an ClassExpression as a initializer
if (ts.isVariableStatement(currentStatement)
&& currentStatement.declarationList.declarations.length === 1) {
const variableDeclaration = currentStatement.declarationList.declarations[0];
if (ts.isIdentifier(variableDeclaration.name)) {
@ -148,6 +153,23 @@ function visitBlockStatements(
oIndex += enumStatements.length;
continue;
}
} else if (ts.isClassExpression(variableDeclaration.initializer)) {
const classStatements = findClassExpressionStatements(name, statements, oIndex);
if (!classStatements) {
continue;
}
if (!updatedStatements) {
updatedStatements = [...statements];
}
updatedStatements.splice(uIndex, classStatements.length, createWrappedClass(
name,
classStatements,
));
oIndex += classStatements.length - 1;
continue;
}
}
}
@ -389,7 +411,6 @@ function updateHostNode(
hostNode: ts.VariableStatement,
expression: ts.Expression,
): ts.Statement {
// Update existing host node with the pure comment before the variable declaration initializer.
const variableDeclaration = hostNode.declarationList.declarations[0];
const outerVarStmt = ts.updateVariableStatement(
@ -411,6 +432,54 @@ function updateHostNode(
return outerVarStmt;
}
/**
* Find class expression statements.
*
* The classExpressions block to wrap in an iife must
* - end with an ExpressionStatement
* - it's expression must be a BinaryExpression
* - have the same name
*
* ```
let Foo = class Foo {};
Foo = __decorate([]);
```
*/
function findClassExpressionStatements(
name: string,
statements: ts.NodeArray<ts.Statement>,
statementIndex: number,
): ts.Statement[] | undefined {
let index = statementIndex + 1;
let statement = statements[index];
while (ts.isExpressionStatement(statement)) {
const expression = statement.expression;
if (ts.isCallExpression(expression)) {
// Ex:
// __decorate([propDecorator()], FooClass, "propertyName", void 0);
// __decorate$1([propDecorator()], FooClass, "propertyName", void 0);
const callExpression = expression.expression;
if (!ts.isIdentifier(callExpression) || !/^__decorate(\$\d+)?$/.test(callExpression.text)) {
break;
}
}
if (
ts.isBinaryExpression(expression)
&& ts.isIdentifier(expression.left)
&& expression.left.getText() === name
) {
// Ex: FooClass = __decorate([Component()], FooClass);
return statements.slice(statementIndex, index + 1);
}
statement = statements[++index];
}
return undefined;
}
function updateEnumIife(
hostNode: ts.VariableStatement,
iife: ts.CallExpression,
@ -474,11 +543,9 @@ function createWrappedEnum(
name: string,
hostNode: ts.VariableStatement,
statements: Array<ts.Statement>,
literalInitializer: ts.ObjectLiteralExpression | undefined,
literalInitializer: ts.ObjectLiteralExpression = ts.createObjectLiteral(),
addExportModifier = false,
): ts.Statement {
literalInitializer = literalInitializer || ts.createObjectLiteral();
const node = addExportModifier
? ts.updateVariableStatement(
hostNode,
@ -504,3 +571,24 @@ function createWrappedEnum(
return updateHostNode(node, addPureComment(ts.createParen(iife)));
}
function createWrappedClass(
name: string,
statements: ts.Statement[],
): ts.Statement {
const pureIife = addPureComment(
ts.createImmediatelyInvokedArrowFunction([
...statements,
ts.createReturn(ts.createIdentifier(name)),
]),
);
return ts.createVariableStatement(
undefined,
ts.createVariableDeclarationList([
ts.createVariableDeclaration(name, undefined, pureIife),
],
ts.NodeFlags.Const,
),
);
}

View File

@ -15,200 +15,324 @@ const transform = (content: string) => transformJavascript(
{ content, getTransforms: [getWrapEnumsTransformer] }).content;
// tslint:disable-next-line:no-big-function
describe('wrap-enums', () => {
it('wraps ts 2.2 enums in IIFE', () => {
const input = tags.stripIndent`
export var ChangeDetectionStrategy = {};
ChangeDetectionStrategy.OnPush = 0;
ChangeDetectionStrategy.Default = 1;
ChangeDetectionStrategy[ChangeDetectionStrategy.OnPush] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy.Default] = "Default";
`;
const output = tags.stripIndent`
export var ChangeDetectionStrategy = /*@__PURE__*/ (function () {
var ChangeDetectionStrategy = {};
describe('wrap enums and classes transformer', () => {
describe('wrap class expressions', () => {
it('should wrap ClassExpression without property decorators in IIFE', () => {
const input = tags.stripIndent`
let AggregateColumnDirective = class AggregateColumnDirective {
constructor(viewContainerRef) { }
};
AggregateColumnDirective = __decorate([
Directive({}),
__metadata("design:paramtypes", [ViewContainerRef])
], AggregateColumnDirective);
`;
const output = tags.stripIndent`
const AggregateColumnDirective = /*@__PURE__*/ (() => {
${input}
return AggregateColumnDirective;
})();
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('should wrap ClassExpression with property decorators in IIFE', () => {
const input = tags.stripIndent`
let ChipList = class ChipList extends Component {
constructor(options, element) {
super(options, element);
}
};
__decorate$4([Property([])], ChipList.prototype, "chips", void 0);
ChipList = __decorate$4([NotifyPropertyChanges], ChipList);
`;
const output = tags.stripIndent`
const ChipList = /*@__PURE__*/ (() => {
${input}
return ChipList;
})();`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('should not wrap ClassExpression without decorators', () => {
const input = tags.stripIndent`
let ChipList = class ChipList extends Component {
constructor(options, element) {
super(options, element);
}
};
fooBar();
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${input}`);
});
it('should wrap ClassExpression with property decorators and static property in IIFE', () => {
const input = tags.stripIndent`
let ChipList = class ChipList extends Component {
constructor(options, element) {
super(options, element);
}
};
ChipList.prop = 1;
__decorate$4([Property([])], ChipList.prototype, "chips", void 0);
ChipList = __decorate$4([NotifyPropertyChanges], ChipList);`;
const output = tags.stripIndent`
const ChipList = /*@__PURE__*/ (() => {
${input}
return ChipList;
})();`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('should wrap multiple ClassExpression in IIFE', () => {
const firstClass = `
let AggregateColumnDirective = class AggregateColumnDirective {
constructor(viewContainerRef) { }
};
AggregateColumnDirective = __decorate([
Directive({}),
__metadata("design:paramtypes", [ViewContainerRef])
], AggregateColumnDirective);
`;
const secondClass = `
let ChipList = class ChipList extends Component {
constructor(options, element) {
super(options, element);
}
};
__decorate$4([Property([])], ChipList.prototype, "chips", void 0);
ChipList = __decorate$4([NotifyPropertyChanges], ChipList);
`;
const input = tags.stripIndent`
const minutesMilliSeconds = 60000;
${firstClass}
const CSS = 'e-css';
const PRIMARY = 'e-primary';
${secondClass}
const chipList = new ChipList({}, {});
`;
const output = tags.stripIndent`
const minutesMilliSeconds = 60000;
const AggregateColumnDirective = /*@__PURE__*/ (() => {
${firstClass}
return AggregateColumnDirective;
})();
const CSS = 'e-css';
const PRIMARY = 'e-primary';
const ChipList = /*@__PURE__*/ (() => {
${secondClass}
return ChipList;
})();
const chipList = new ChipList({}, {});
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
});
// tslint:disable-next-line:no-big-function
describe('wrap enums', () => {
it('wraps ts 2.2 enums in IIFE', () => {
const input = tags.stripIndent`
export var ChangeDetectionStrategy = {};
ChangeDetectionStrategy.OnPush = 0;
ChangeDetectionStrategy.Default = 1;
ChangeDetectionStrategy[ChangeDetectionStrategy.OnPush] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy.Default] = "Default";
return ChangeDetectionStrategy;
}());
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('wraps ES2015 tsickle enums in IIFE', () => {
const input = tags.stripIndent`
const ChangeDetectionStrategy = {
OnPush: 0,
Default: 1,
};
export { ChangeDetectionStrategy };
ChangeDetectionStrategy[ChangeDetectionStrategy.OnPush] = 'OnPush';
ChangeDetectionStrategy[ChangeDetectionStrategy.Default] = 'Default';
`;
const output = tags.stripIndent`
export const ChangeDetectionStrategy = /*@__PURE__*/ (function () {
var ChangeDetectionStrategy = { OnPush: 0, Default: 1, };
ChangeDetectionStrategy[ChangeDetectionStrategy.OnPush] = 'OnPush';
ChangeDetectionStrategy[ChangeDetectionStrategy.Default] = 'Default';
`;
const output = tags.stripIndent`
export var ChangeDetectionStrategy = /*@__PURE__*/ (function () {
var ChangeDetectionStrategy = {};
ChangeDetectionStrategy.OnPush = 0;
ChangeDetectionStrategy.Default = 1;
ChangeDetectionStrategy[ChangeDetectionStrategy.OnPush] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy.Default] = "Default";
return ChangeDetectionStrategy;
}());
`;
}());
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('wraps only ES2015 tsickle enums in IIFE', () => {
const input = tags.stripIndent`
const RendererStyleFlags3 = {
Important: 1,
DashCase: 2,
};
export { RendererStyleFlags3 };
RendererStyleFlags3[RendererStyleFlags3.Important] = 'Important';
RendererStyleFlags3[RendererStyleFlags3.DashCase] = 'DashCase';
it('wraps ES2015 tsickle enums in IIFE', () => {
const input = tags.stripIndent`
const ChangeDetectionStrategy = {
OnPush: 0,
Default: 1,
};
export { ChangeDetectionStrategy };
ChangeDetectionStrategy[ChangeDetectionStrategy.OnPush] = 'OnPush';
ChangeDetectionStrategy[ChangeDetectionStrategy.Default] = 'Default';
`;
export const domRendererFactory3 = {
createRenderer: (hostElement, rendererType) => { return document; }
};
const output = tags.stripIndent`
export const ChangeDetectionStrategy = /*@__PURE__*/ (function () {
var ChangeDetectionStrategy = { OnPush: 0, Default: 1, };
export const unusedValueExportToPlacateAjd = 1;
`;
const output = tags.stripIndent`
export const RendererStyleFlags3 = /*@__PURE__*/ (function () {
var RendererStyleFlags3 = { Important: 1, DashCase: 2, };
ChangeDetectionStrategy[ChangeDetectionStrategy.OnPush] = 'OnPush';
ChangeDetectionStrategy[ChangeDetectionStrategy.Default] = 'Default';
return ChangeDetectionStrategy;
}());
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('wraps only ES2015 tsickle enums in IIFE', () => {
const input = tags.stripIndent`
const RendererStyleFlags3 = {
Important: 1,
DashCase: 2,
};
export { RendererStyleFlags3 };
RendererStyleFlags3[RendererStyleFlags3.Important] = 'Important';
RendererStyleFlags3[RendererStyleFlags3.DashCase] = 'DashCase';
return RendererStyleFlags3;
}());
export const domRendererFactory3 = {
createRenderer: (hostElement, rendererType) => { return document; }
};
export const domRendererFactory3 = {
createRenderer: (hostElement, rendererType) => { return document; }
};
export const unusedValueExportToPlacateAjd = 1;
`;
export const unusedValueExportToPlacateAjd = 1;
`;
const output = tags.stripIndent`
export const RendererStyleFlags3 = /*@__PURE__*/ (function () {
var RendererStyleFlags3 = { Important: 1, DashCase: 2, };
RendererStyleFlags3[RendererStyleFlags3.Important] = 'Important';
RendererStyleFlags3[RendererStyleFlags3.DashCase] = 'DashCase';
return RendererStyleFlags3;
}());
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
export const domRendererFactory3 = {
createRenderer: (hostElement, rendererType) => { return document; }
};
it('wraps ts >2.3 enums in IIFE', () => {
const input = tags.stripIndent`
export var ChangeDetectionStrategy;
(function (ChangeDetectionStrategy) {
export const unusedValueExportToPlacateAjd = 1;
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('wraps ts >2.3 enums in IIFE', () => {
const input = tags.stripIndent`
export var ChangeDetectionStrategy;
(function (ChangeDetectionStrategy) {
ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
})(ChangeDetectionStrategy || (ChangeDetectionStrategy = {}));
`;
const output = tags.stripIndent`
export var ChangeDetectionStrategy = /*@__PURE__*/ (function (ChangeDetectionStrategy) {
ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
})(ChangeDetectionStrategy || (ChangeDetectionStrategy = {}));
`;
const output = tags.stripIndent`
export var ChangeDetectionStrategy = /*@__PURE__*/ (function (ChangeDetectionStrategy) {
ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
return ChangeDetectionStrategy;
})({});
`;
return ChangeDetectionStrategy;
})({});
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('wraps ts >2.3 enums in IIFE, even if they have funny numbers', () => {
const input = tags.stripIndent`
export var AnimatorControlState;
(function (AnimatorControlState) {
AnimatorControlState[AnimatorControlState["INITIALIZED"] = 1] = "INITIALIZED";
AnimatorControlState[AnimatorControlState["STARTED"] = 2] = "STARTED";
AnimatorControlState[AnimatorControlState["FINISHED"] = 3] = "FINISHED";
AnimatorControlState[AnimatorControlState["DESTROYED"] = 4] = "DESTROYED";
})(AnimatorControlState || (AnimatorControlState = {}));
`;
const output = tags.stripIndent`
export var AnimatorControlState = /*@__PURE__*/ (function (AnimatorControlState) {
AnimatorControlState[AnimatorControlState["INITIALIZED"] = 1] = "INITIALIZED";
AnimatorControlState[AnimatorControlState["STARTED"] = 2] = "STARTED";
AnimatorControlState[AnimatorControlState["FINISHED"] = 3] = "FINISHED";
AnimatorControlState[AnimatorControlState["DESTROYED"] = 4] = "DESTROYED";
return AnimatorControlState;
})({});
`;
it('wraps ts >2.3 enums in IIFE, even if they have funny numbers', () => {
const input = tags.stripIndent`
export var AnimatorControlState;
(function (AnimatorControlState) {
AnimatorControlState[AnimatorControlState["INITIALIZED"] = 1] = "INITIALIZED";
AnimatorControlState[AnimatorControlState["STARTED"] = 2] = "STARTED";
AnimatorControlState[AnimatorControlState["FINISHED"] = 3] = "FINISHED";
AnimatorControlState[AnimatorControlState["DESTROYED"] = 4] = "DESTROYED";
})(AnimatorControlState || (AnimatorControlState = {}));
`;
const output = tags.stripIndent`
export var AnimatorControlState = /*@__PURE__*/ (function (AnimatorControlState) {
AnimatorControlState[AnimatorControlState["INITIALIZED"] = 1] = "INITIALIZED";
AnimatorControlState[AnimatorControlState["STARTED"] = 2] = "STARTED";
AnimatorControlState[AnimatorControlState["FINISHED"] = 3] = "FINISHED";
AnimatorControlState[AnimatorControlState["DESTROYED"] = 4] = "DESTROYED";
return AnimatorControlState;
})({});
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('wraps ts >2.3 enums in IIFE, even if they were renamed due to scope hoisting', () => {
const input = tags.stripIndent`
var TokenType$1;
(function (TokenType) {
TokenType[TokenType["TAG_OPEN_START"] = 0] = "TAG_OPEN_START";
TokenType[TokenType["TAG_OPEN_END"] = 1] = "TAG_OPEN_END";
TokenType[TokenType["TAG_OPEN_END_VOID"] = 2] = "TAG_OPEN_END_VOID";
TokenType[TokenType["TAG_CLOSE"] = 3] = "TAG_CLOSE";
TokenType[TokenType["TEXT"] = 4] = "TEXT";
TokenType[TokenType["ESCAPABLE_RAW_TEXT"] = 5] = "ESCAPABLE_RAW_TEXT";
TokenType[TokenType["RAW_TEXT"] = 6] = "RAW_TEXT";
TokenType[TokenType["COMMENT_START"] = 7] = "COMMENT_START";
TokenType[TokenType["COMMENT_END"] = 8] = "COMMENT_END";
TokenType[TokenType["CDATA_START"] = 9] = "CDATA_START";
TokenType[TokenType["CDATA_END"] = 10] = "CDATA_END";
TokenType[TokenType["ATTR_NAME"] = 11] = "ATTR_NAME";
TokenType[TokenType["ATTR_VALUE"] = 12] = "ATTR_VALUE";
TokenType[TokenType["DOC_TYPE"] = 13] = "DOC_TYPE";
TokenType[TokenType["EXPANSION_FORM_START"] = 14] = "EXPANSION_FORM_START";
TokenType[TokenType["EXPANSION_CASE_VALUE"] = 15] = "EXPANSION_CASE_VALUE";
TokenType[TokenType["EXPANSION_CASE_EXP_START"] = 16] = "EXPANSION_CASE_EXP_START";
TokenType[TokenType["EXPANSION_CASE_EXP_END"] = 17] = "EXPANSION_CASE_EXP_END";
TokenType[TokenType["EXPANSION_FORM_END"] = 18] = "EXPANSION_FORM_END";
TokenType[TokenType["EOF"] = 19] = "EOF";
})(TokenType$1 || (TokenType$1 = {}));
`;
const output = tags.stripIndent`
var TokenType$1 = /*@__PURE__*/ (function (TokenType) {
TokenType[TokenType["TAG_OPEN_START"] = 0] = "TAG_OPEN_START";
TokenType[TokenType["TAG_OPEN_END"] = 1] = "TAG_OPEN_END";
TokenType[TokenType["TAG_OPEN_END_VOID"] = 2] = "TAG_OPEN_END_VOID";
TokenType[TokenType["TAG_CLOSE"] = 3] = "TAG_CLOSE";
TokenType[TokenType["TEXT"] = 4] = "TEXT";
TokenType[TokenType["ESCAPABLE_RAW_TEXT"] = 5] = "ESCAPABLE_RAW_TEXT";
TokenType[TokenType["RAW_TEXT"] = 6] = "RAW_TEXT";
TokenType[TokenType["COMMENT_START"] = 7] = "COMMENT_START";
TokenType[TokenType["COMMENT_END"] = 8] = "COMMENT_END";
TokenType[TokenType["CDATA_START"] = 9] = "CDATA_START";
TokenType[TokenType["CDATA_END"] = 10] = "CDATA_END";
TokenType[TokenType["ATTR_NAME"] = 11] = "ATTR_NAME";
TokenType[TokenType["ATTR_VALUE"] = 12] = "ATTR_VALUE";
TokenType[TokenType["DOC_TYPE"] = 13] = "DOC_TYPE";
TokenType[TokenType["EXPANSION_FORM_START"] = 14] = "EXPANSION_FORM_START";
TokenType[TokenType["EXPANSION_CASE_VALUE"] = 15] = "EXPANSION_CASE_VALUE";
TokenType[TokenType["EXPANSION_CASE_EXP_START"] = 16] = "EXPANSION_CASE_EXP_START";
TokenType[TokenType["EXPANSION_CASE_EXP_END"] = 17] = "EXPANSION_CASE_EXP_END";
TokenType[TokenType["EXPANSION_FORM_END"] = 18] = "EXPANSION_FORM_END";
TokenType[TokenType["EOF"] = 19] = "EOF";
return TokenType;
})({});
`;
it('wraps ts >2.3 enums in IIFE, even if they were renamed due to scope hoisting', () => {
const input = tags.stripIndent`
var TokenType$1;
(function (TokenType) {
TokenType[TokenType["TAG_OPEN_START"] = 0] = "TAG_OPEN_START";
TokenType[TokenType["TAG_OPEN_END"] = 1] = "TAG_OPEN_END";
TokenType[TokenType["TAG_OPEN_END_VOID"] = 2] = "TAG_OPEN_END_VOID";
TokenType[TokenType["TAG_CLOSE"] = 3] = "TAG_CLOSE";
TokenType[TokenType["TEXT"] = 4] = "TEXT";
TokenType[TokenType["ESCAPABLE_RAW_TEXT"] = 5] = "ESCAPABLE_RAW_TEXT";
TokenType[TokenType["RAW_TEXT"] = 6] = "RAW_TEXT";
TokenType[TokenType["COMMENT_START"] = 7] = "COMMENT_START";
TokenType[TokenType["COMMENT_END"] = 8] = "COMMENT_END";
TokenType[TokenType["CDATA_START"] = 9] = "CDATA_START";
TokenType[TokenType["CDATA_END"] = 10] = "CDATA_END";
TokenType[TokenType["ATTR_NAME"] = 11] = "ATTR_NAME";
TokenType[TokenType["ATTR_VALUE"] = 12] = "ATTR_VALUE";
TokenType[TokenType["DOC_TYPE"] = 13] = "DOC_TYPE";
TokenType[TokenType["EXPANSION_FORM_START"] = 14] = "EXPANSION_FORM_START";
TokenType[TokenType["EXPANSION_CASE_VALUE"] = 15] = "EXPANSION_CASE_VALUE";
TokenType[TokenType["EXPANSION_CASE_EXP_START"] = 16] = "EXPANSION_CASE_EXP_START";
TokenType[TokenType["EXPANSION_CASE_EXP_END"] = 17] = "EXPANSION_CASE_EXP_END";
TokenType[TokenType["EXPANSION_FORM_END"] = 18] = "EXPANSION_FORM_END";
TokenType[TokenType["EOF"] = 19] = "EOF";
})(TokenType$1 || (TokenType$1 = {}));
`;
const output = tags.stripIndent`
var TokenType$1 = /*@__PURE__*/ (function (TokenType) {
TokenType[TokenType["TAG_OPEN_START"] = 0] = "TAG_OPEN_START";
TokenType[TokenType["TAG_OPEN_END"] = 1] = "TAG_OPEN_END";
TokenType[TokenType["TAG_OPEN_END_VOID"] = 2] = "TAG_OPEN_END_VOID";
TokenType[TokenType["TAG_CLOSE"] = 3] = "TAG_CLOSE";
TokenType[TokenType["TEXT"] = 4] = "TEXT";
TokenType[TokenType["ESCAPABLE_RAW_TEXT"] = 5] = "ESCAPABLE_RAW_TEXT";
TokenType[TokenType["RAW_TEXT"] = 6] = "RAW_TEXT";
TokenType[TokenType["COMMENT_START"] = 7] = "COMMENT_START";
TokenType[TokenType["COMMENT_END"] = 8] = "COMMENT_END";
TokenType[TokenType["CDATA_START"] = 9] = "CDATA_START";
TokenType[TokenType["CDATA_END"] = 10] = "CDATA_END";
TokenType[TokenType["ATTR_NAME"] = 11] = "ATTR_NAME";
TokenType[TokenType["ATTR_VALUE"] = 12] = "ATTR_VALUE";
TokenType[TokenType["DOC_TYPE"] = 13] = "DOC_TYPE";
TokenType[TokenType["EXPANSION_FORM_START"] = 14] = "EXPANSION_FORM_START";
TokenType[TokenType["EXPANSION_CASE_VALUE"] = 15] = "EXPANSION_CASE_VALUE";
TokenType[TokenType["EXPANSION_CASE_EXP_START"] = 16] = "EXPANSION_CASE_EXP_START";
TokenType[TokenType["EXPANSION_CASE_EXP_END"] = 17] = "EXPANSION_CASE_EXP_END";
TokenType[TokenType["EXPANSION_FORM_END"] = 18] = "EXPANSION_FORM_END";
TokenType[TokenType["EOF"] = 19] = "EOF";
return TokenType;
})({});
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('wraps tsickle enums in IIFE', () => {
const input = tags.stripIndent`
/** @enum {number} */
var FormatWidth = {
Short: 0,
Medium: 1,
Long: 2,
Full: 3,
};
FormatWidth[FormatWidth.Short] = "Short";
FormatWidth[FormatWidth.Medium] = "Medium";
FormatWidth[FormatWidth.Long] = "Long";
FormatWidth[FormatWidth.Full] = "Full";
`;
const output = tags.stripIndent`
/** @enum {number} */ var FormatWidth = /*@__PURE__*/ (function () {
it('wraps tsickle enums in IIFE', () => {
const input = tags.stripIndent`
/** @enum {number} */
var FormatWidth = {
Short: 0,
Medium: 1,
@ -219,81 +343,94 @@ describe('wrap-enums', () => {
FormatWidth[FormatWidth.Medium] = "Medium";
FormatWidth[FormatWidth.Long] = "Long";
FormatWidth[FormatWidth.Full] = "Full";
return FormatWidth;
}());
`;
`;
const output = tags.stripIndent`
/** @enum {number} */ var FormatWidth = /*@__PURE__*/ (function () {
var FormatWidth = {
Short: 0,
Medium: 1,
Long: 2,
Full: 3,
};
FormatWidth[FormatWidth.Short] = "Short";
FormatWidth[FormatWidth.Medium] = "Medium";
FormatWidth[FormatWidth.Long] = "Long";
FormatWidth[FormatWidth.Full] = "Full";
return FormatWidth;
}());
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('wraps enums with multi-line comments in IIFE', () => {
const input = tags.stripIndent`
/**
* Supported http methods.
* @deprecated use @angular/common/http instead
*/
var RequestMethod;
/**
* Supported http methods.
* @deprecated use @angular/common/http instead
*/
(function (RequestMethod) {
RequestMethod[RequestMethod["Get"] = 0] = "Get";
RequestMethod[RequestMethod["Post"] = 1] = "Post";
RequestMethod[RequestMethod["Put"] = 2] = "Put";
RequestMethod[RequestMethod["Delete"] = 3] = "Delete";
RequestMethod[RequestMethod["Options"] = 4] = "Options";
RequestMethod[RequestMethod["Head"] = 5] = "Head";
RequestMethod[RequestMethod["Patch"] = 6] = "Patch";
})(RequestMethod || (RequestMethod = {}));
`;
// We need to interpolate this space because our editorconfig automatically strips
// trailing whitespace.
const space = ' ';
const output = tags.stripIndent`
/**
* Supported http methods.
* @deprecated use @angular/common/http instead
*/
var RequestMethod =${space}
/**
* Supported http methods.
* @deprecated use @angular/common/http instead
*/
/*@__PURE__*/ (function (RequestMethod) {
RequestMethod[RequestMethod["Get"] = 0] = "Get";
RequestMethod[RequestMethod["Post"] = 1] = "Post";
RequestMethod[RequestMethod["Put"] = 2] = "Put";
RequestMethod[RequestMethod["Delete"] = 3] = "Delete";
RequestMethod[RequestMethod["Options"] = 4] = "Options";
RequestMethod[RequestMethod["Head"] = 5] = "Head";
RequestMethod[RequestMethod["Patch"] = 6] = "Patch";
return RequestMethod;
})({});
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('wraps exported enums in IIFE', () => {
const input = tags.stripIndent`
var ExportEnum;
(function (ExportEnum) {
ExportEnum[ExportEnum["A"] = 0] = "A";
ExportEnum[ExportEnum["B"] = 1] = "B";
ExportEnum[ExportEnum["C"] = 2] = "C";
})(ExportEnum = exports.ExportEnum || (exports.ExportEnum = {}));
`;
const output = tags.stripIndent`
var ExportEnum = exports.ExportEnum = /*@__PURE__*/ (function (ExportEnum) {
ExportEnum[ExportEnum["A"] = 0] = "A";
ExportEnum[ExportEnum["B"] = 1] = "B";
ExportEnum[ExportEnum["C"] = 2] = "C";
return ExportEnum;
})(exports.ExportEnum || {});
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
});
it('wraps enums with multi-line comments in IIFE', () => {
const input = tags.stripIndent`
/**
* Supported http methods.
* @deprecated use @angular/common/http instead
*/
var RequestMethod;
/**
* Supported http methods.
* @deprecated use @angular/common/http instead
*/
(function (RequestMethod) {
RequestMethod[RequestMethod["Get"] = 0] = "Get";
RequestMethod[RequestMethod["Post"] = 1] = "Post";
RequestMethod[RequestMethod["Put"] = 2] = "Put";
RequestMethod[RequestMethod["Delete"] = 3] = "Delete";
RequestMethod[RequestMethod["Options"] = 4] = "Options";
RequestMethod[RequestMethod["Head"] = 5] = "Head";
RequestMethod[RequestMethod["Patch"] = 6] = "Patch";
})(RequestMethod || (RequestMethod = {}));
`;
// We need to interpolate this space because our editorconfig automatically strips
// trailing whitespace.
const space = ' ';
const output = tags.stripIndent`
/**
* Supported http methods.
* @deprecated use @angular/common/http instead
*/
var RequestMethod =${space}
/**
* Supported http methods.
* @deprecated use @angular/common/http instead
*/
/*@__PURE__*/ (function (RequestMethod) {
RequestMethod[RequestMethod["Get"] = 0] = "Get";
RequestMethod[RequestMethod["Post"] = 1] = "Post";
RequestMethod[RequestMethod["Put"] = 2] = "Put";
RequestMethod[RequestMethod["Delete"] = 3] = "Delete";
RequestMethod[RequestMethod["Options"] = 4] = "Options";
RequestMethod[RequestMethod["Head"] = 5] = "Head";
RequestMethod[RequestMethod["Patch"] = 6] = "Patch";
return RequestMethod;
})({});
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
it('wraps exported enums in IIFE', () => {
const input = tags.stripIndent`
var ExportEnum;
(function (ExportEnum) {
ExportEnum[ExportEnum["A"] = 0] = "A";
ExportEnum[ExportEnum["B"] = 1] = "B";
ExportEnum[ExportEnum["C"] = 2] = "C";
})(ExportEnum = exports.ExportEnum || (exports.ExportEnum = {}));
`;
const output = tags.stripIndent`
var ExportEnum = exports.ExportEnum = /*@__PURE__*/ (function (ExportEnum) {
ExportEnum[ExportEnum["A"] = 0] = "A";
ExportEnum[ExportEnum["B"] = 1] = "B";
ExportEnum[ExportEnum["C"] = 2] = "C";
return ExportEnum;
})(exports.ExportEnum || {});
`;
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
});