feat(compiler-cli): support producing Closure-specific PURE annotations (#41021)

For certain generated function calls, the compiler emits a 'PURE' annotation
which informs Terser (the optimizer) about the purity of a specific function
call. This commit expands that system to produce a new Closure-specific
'pureOrBreakMyCode' annotation when targeting the Closure optimizer instead
of Terser.

PR Close #41021
This commit is contained in:
Alex Rickabaugh
2021-02-26 11:55:19 -08:00
committed by Andrew Kushnir
parent 45216ccc0d
commit fbc9df181e
12 changed files with 81 additions and 25 deletions
@@ -23,7 +23,7 @@ interface TestObject {
}
const host: AstHost<ts.Expression> = new TypeScriptAstHost();
const factory = new TypeScriptAstFactory();
const factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false);
const nestedObj = factory.createObjectLiteral([
{propertyName: 'x', quoted: false, value: factory.createLiteral(42)},
{propertyName: 'y', quoted: false, value: factory.createLiteral('X')},
@@ -16,7 +16,7 @@ import {generate} from '../helpers';
describe('EmitScope', () => {
describe('translateDefinition()', () => {
it('should translate the given output AST into a TExpression', () => {
const factory = new TypeScriptAstFactory();
const factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false);
const translator = new Translator<ts.Statement, ts.Expression>(factory);
const ngImport = factory.createIdentifier('core');
const emitScope = new EmitScope<ts.Statement, ts.Expression>(ngImport, translator);
@@ -26,7 +26,7 @@ describe('EmitScope', () => {
});
it('should use the `ngImport` idenfifier for imports when translating', () => {
const factory = new TypeScriptAstFactory();
const factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false);
const translator = new Translator<ts.Statement, ts.Expression>(factory);
const ngImport = factory.createIdentifier('core');
const emitScope = new EmitScope<ts.Statement, ts.Expression>(ngImport, translator);
@@ -37,7 +37,7 @@ describe('EmitScope', () => {
});
it('should not emit any shared constants in the replacement expression', () => {
const factory = new TypeScriptAstFactory();
const factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false);
const translator = new Translator<ts.Statement, ts.Expression>(factory);
const ngImport = factory.createIdentifier('core');
const emitScope = new EmitScope<ts.Statement, ts.Expression>(ngImport, translator);
@@ -54,7 +54,7 @@ describe('EmitScope', () => {
describe('getConstantStatements()', () => {
it('should return any constant statements that were added to the `constantPool`', () => {
const factory = new TypeScriptAstFactory();
const factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false);
const translator = new Translator<ts.Statement, ts.Expression>(factory);
const ngImport = factory.createIdentifier('core');
const emitScope = new EmitScope<ts.Statement, ts.Expression>(ngImport, translator);
@@ -16,7 +16,7 @@ import {generate} from '../helpers';
describe('IifeEmitScope', () => {
describe('translateDefinition()', () => {
it('should translate the given output AST into a TExpression, wrapped in an IIFE', () => {
const factory = new TypeScriptAstFactory();
const factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false);
const translator = new Translator<ts.Statement, ts.Expression>(factory);
const ngImport = factory.createIdentifier('core');
const emitScope =
@@ -27,7 +27,7 @@ describe('IifeEmitScope', () => {
});
it('should use the `ngImport` idenfifier for imports when translating', () => {
const factory = new TypeScriptAstFactory();
const factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false);
const translator = new Translator<ts.Statement, ts.Expression>(factory);
const ngImport = factory.createIdentifier('core');
const emitScope =
@@ -39,7 +39,7 @@ describe('IifeEmitScope', () => {
});
it('should emit any shared constants in the replacement expression IIFE', () => {
const factory = new TypeScriptAstFactory();
const factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false);
const translator = new Translator<ts.Statement, ts.Expression>(factory);
const ngImport = factory.createIdentifier('core');
const emitScope =
@@ -58,7 +58,7 @@ describe('IifeEmitScope', () => {
describe('getConstantStatements()', () => {
it('should throw an error', () => {
const factory = new TypeScriptAstFactory();
const factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false);
const translator = new Translator<ts.Statement, ts.Expression>(factory);
const ngImport = factory.createIdentifier('core');
const emitScope =
@@ -23,7 +23,7 @@ import {generate} from './helpers';
describe('FileLinker', () => {
let factory: TypeScriptAstFactory;
beforeEach(() => factory = new TypeScriptAstFactory());
beforeEach(() => factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false));
describe('isPartialDeclaration()', () => {
it('should return true if the callee is recognized', () => {
@@ -154,7 +154,8 @@ describe('FileLinker', () => {
const fs = new MockFileSystemNative();
const logger = new MockLogger();
const linkerEnvironment = LinkerEnvironment.create<ts.Statement, ts.Expression>(
fs, logger, new TypeScriptAstHost(), new TypeScriptAstFactory(), DEFAULT_LINKER_OPTIONS);
fs, logger, new TypeScriptAstHost(),
new TypeScriptAstFactory(/* annotateForClosureCompiler */ false), DEFAULT_LINKER_OPTIONS);
const fileLinker = new FileLinker<MockConstantScopeRef, ts.Statement, ts.Expression>(
linkerEnvironment, fs.resolve('/test.js'), '// test code');
return {host: linkerEnvironment.host, fileLinker};
@@ -33,7 +33,8 @@ describe('PartialLinkerSelector', () => {
fs = new MockFileSystemNative();
const logger = new MockLogger();
environment = LinkerEnvironment.create<ts.Statement, ts.Expression>(
fs, logger, new TypeScriptAstHost(), new TypeScriptAstFactory(), options);
fs, logger, new TypeScriptAstHost(),
new TypeScriptAstFactory(/* annotateForClosureCompiler */ false), options);
});
describe('supportsDeclaration()', () => {
@@ -14,7 +14,7 @@ import {generate} from './helpers';
describe('Translator', () => {
let factory: TypeScriptAstFactory;
beforeEach(() => factory = new TypeScriptAstFactory());
beforeEach(() => factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false));
describe('translateExpression()', () => {
it('should generate expression specific output', () => {