mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-18 11:44:05 +08:00
fix(@angular-devkit/build-optimizer): don't add pure comments to tslib helpers (#15303)
Closes #15301
This commit is contained in:
parent
b3b45469f5
commit
e2bb482b44
@ -28,6 +28,7 @@ ts_library(
|
|||||||
"@npm//@types/node",
|
"@npm//@types/node",
|
||||||
"@npm//@types/webpack",
|
"@npm//@types/webpack",
|
||||||
"@npm//source-map",
|
"@npm//source-map",
|
||||||
|
"@npm//tslib",
|
||||||
"@npm//typescript",
|
"@npm//typescript",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loader-utils": "1.2.3",
|
"loader-utils": "1.2.3",
|
||||||
"source-map": "0.7.3",
|
"source-map": "0.7.3",
|
||||||
|
"tslib": "1.10.0",
|
||||||
"typescript": "3.5.3",
|
"typescript": "3.5.3",
|
||||||
"webpack-sources": "1.4.3"
|
"webpack-sources": "1.4.3"
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,44 @@ describe('build-optimizer', () => {
|
|||||||
expect(boOutput.emitSkipped).toEqual(false);
|
expect(boOutput.emitSkipped).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it(`doesn't add pure comments to tslib helpers`, () => {
|
||||||
|
const input = tags.stripIndent`
|
||||||
|
class LanguageState {
|
||||||
|
}
|
||||||
|
|
||||||
|
LanguageState.ctorParameters = () => [
|
||||||
|
{ type: TranslateService },
|
||||||
|
{ type: undefined, decorators: [{ type: Inject, args: [LANGUAGE_CONFIG,] }] }
|
||||||
|
];
|
||||||
|
|
||||||
|
__decorate([
|
||||||
|
Action(CheckLanguage),
|
||||||
|
__metadata("design:type", Function),
|
||||||
|
__metadata("design:paramtypes", [Object]),
|
||||||
|
__metadata("design:returntype", void 0)
|
||||||
|
], LanguageState.prototype, "checkLanguage", null);
|
||||||
|
`;
|
||||||
|
|
||||||
|
const output = tags.oneLine`
|
||||||
|
let LanguageState = /*@__PURE__*/ (() => {
|
||||||
|
class LanguageState {
|
||||||
|
}
|
||||||
|
|
||||||
|
__decorate([
|
||||||
|
Action(CheckLanguage),
|
||||||
|
__metadata("design:type", Function),
|
||||||
|
__metadata("design:paramtypes", [Object]),
|
||||||
|
__metadata("design:returntype", void 0)
|
||||||
|
], LanguageState.prototype, "checkLanguage", null);
|
||||||
|
return LanguageState;
|
||||||
|
})();
|
||||||
|
`;
|
||||||
|
|
||||||
|
const boOutput = buildOptimizer({ content: input, isSideEffectFree: true });
|
||||||
|
expect(tags.oneLine`${boOutput.content}`).toEqual(output);
|
||||||
|
expect(boOutput.emitSkipped).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
it('should not wrap classes which had all static properties dropped in IIFE', () => {
|
it('should not wrap classes which had all static properties dropped in IIFE', () => {
|
||||||
const classDeclaration = tags.oneLine`
|
const classDeclaration = tags.oneLine`
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
@ -5,10 +5,15 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
import * as tslib from 'tslib';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
const pureFunctionComment = '@__PURE__';
|
const pureFunctionComment = '@__PURE__';
|
||||||
|
|
||||||
|
// We include only exports that start with '__' because tslib helpers
|
||||||
|
// all start with a suffix of two underscores.
|
||||||
|
const tslibHelpers = new Set<string>(Object.keys(tslib).filter(h => h.startsWith('__')));
|
||||||
|
|
||||||
// Find all nodes from the AST in the subtree of node of SyntaxKind kind.
|
// Find all nodes from the AST in the subtree of node of SyntaxKind kind.
|
||||||
export function collectDeepNodes<T extends ts.Node>(node: ts.Node, kind: ts.SyntaxKind): T[] {
|
export function collectDeepNodes<T extends ts.Node>(node: ts.Node, kind: ts.SyntaxKind): T[] {
|
||||||
const nodes: T[] = [];
|
const nodes: T[] = [];
|
||||||
@ -41,3 +46,7 @@ export function hasPureComment(node: ts.Node): boolean {
|
|||||||
|
|
||||||
return !!leadingComment && leadingComment.some(comment => comment.text === pureFunctionComment);
|
return !!leadingComment && leadingComment.some(comment => comment.text === pureFunctionComment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isHelperName(name: string): boolean {
|
||||||
|
return tslibHelpers.has(name);
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
import { isHelperName } from '../helpers/ast-utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated From 0.9.0
|
* @deprecated From 0.9.0
|
||||||
@ -89,15 +90,3 @@ function createTslibImport(
|
|||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isHelperName(name: string): boolean {
|
|
||||||
// TODO: there are more helpers than these, should we replace them all?
|
|
||||||
const tsHelpers = [
|
|
||||||
'__extends',
|
|
||||||
'__decorate',
|
|
||||||
'__metadata',
|
|
||||||
'__param',
|
|
||||||
];
|
|
||||||
|
|
||||||
return tsHelpers.indexOf(name) !== -1;
|
|
||||||
}
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import { addPureComment, hasPureComment } from '../helpers/ast-utils';
|
import { addPureComment, hasPureComment, isHelperName } from '../helpers/ast-utils';
|
||||||
|
|
||||||
export function getPrefixFunctionsTransformer(): ts.TransformerFactory<ts.SourceFile> {
|
export function getPrefixFunctionsTransformer(): ts.TransformerFactory<ts.SourceFile> {
|
||||||
return (context: ts.TransformationContext): ts.Transformer<ts.SourceFile> => {
|
return (context: ts.TransformationContext): ts.Transformer<ts.SourceFile> => {
|
||||||
@ -44,10 +44,8 @@ export function findTopLevelFunctions(parentNode: ts.Node): Set<ts.Node> {
|
|||||||
// need to mark function calls inside them as pure.
|
// need to mark function calls inside them as pure.
|
||||||
// Class static initializers in ES2015 are an exception we don't cover. They would need similar
|
// Class static initializers in ES2015 are an exception we don't cover. They would need similar
|
||||||
// processing as enums to prevent property setting from causing the class to be retained.
|
// processing as enums to prevent property setting from causing the class to be retained.
|
||||||
if (ts.isFunctionDeclaration(node)
|
if (ts.isFunctionLike(node)
|
||||||
|| ts.isFunctionExpression(node)
|
|| ts.isClassLike(node)
|
||||||
|| ts.isClassDeclaration(node)
|
|
||||||
|| ts.isClassExpression(node)
|
|
||||||
|| ts.isArrowFunction(node)
|
|| ts.isArrowFunction(node)
|
||||||
|| ts.isMethodDeclaration(node)
|
|| ts.isMethodDeclaration(node)
|
||||||
) {
|
) {
|
||||||
@ -78,9 +76,15 @@ export function findTopLevelFunctions(parentNode: ts.Node): Set<ts.Node> {
|
|||||||
topLevelFunctions.add(node);
|
topLevelFunctions.add(node);
|
||||||
} else if (ts.isCallExpression(innerNode)) {
|
} else if (ts.isCallExpression(innerNode)) {
|
||||||
let expression: ts.Expression = innerNode.expression;
|
let expression: ts.Expression = innerNode.expression;
|
||||||
|
|
||||||
|
if (ts.isIdentifier(expression) && isHelperName(expression.text)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (expression && ts.isParenthesizedExpression(expression)) {
|
while (expression && ts.isParenthesizedExpression(expression)) {
|
||||||
expression = expression.expression;
|
expression = expression.expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expression) {
|
if (expression) {
|
||||||
if (ts.isFunctionExpression(expression)) {
|
if (ts.isFunctionExpression(expression)) {
|
||||||
// Skip IIFE's with arguments
|
// Skip IIFE's with arguments
|
||||||
|
@ -186,4 +186,28 @@ describe('prefix-functions', () => {
|
|||||||
|
|
||||||
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
|
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it(`doesn't add pure comments to tslib helpers`, () => {
|
||||||
|
const input = tags.stripIndent`
|
||||||
|
class LanguageState {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
LanguageState.ctorParameters = () => [
|
||||||
|
{ type: TranslateService },
|
||||||
|
{ type: undefined, decorators: [{ type: Inject, args: [LANGUAGE_CONFIG,] }] }
|
||||||
|
];
|
||||||
|
|
||||||
|
__decorate([
|
||||||
|
Action(CheckLanguage),
|
||||||
|
__metadata("design:type", Function),
|
||||||
|
__metadata("design:paramtypes", [Object]),
|
||||||
|
__metadata("design:returntype", void 0)
|
||||||
|
], LanguageState.prototype, "checkLanguage", null);
|
||||||
|
`;
|
||||||
|
|
||||||
|
const output = input;
|
||||||
|
|
||||||
|
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user