fix(ngcc): ensure that adjacent statements go after helper calls (#33689)
Previously the renderers were fixed so that they inserted extra "adjacent" statements after the last static property of classes. In order to help the build-optimizer (in Angular CLI) to be able to tree-shake classes effectively, these statements should also appear after any helper calls, such as `__decorate()`. This commit moves the computation of this positioning into the `NgccReflectionHost` via the `getEndOfClass()` method, which returns the last statement that is related to the class. FW-1668 PR Close #33689
This commit is contained in:

committed by
Kara Erickson

parent
f67802ddc0
commit
c5400616f8
@ -486,6 +486,20 @@ runInEachFileSystem(() => {
|
||||
expect(value).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getEndOfClass()', () => {
|
||||
it('should return the last statement related to the class', () => {
|
||||
const {program} = makeTestBundleProgram(_('/ngmodule.js'));
|
||||
const host =
|
||||
new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
const classSymbol =
|
||||
host.findClassSymbols(program.getSourceFile(_('/ngmodule.js')) !)[0];
|
||||
const endOfClass = host.getEndOfClass(classSymbol);
|
||||
expect(endOfClass.getText())
|
||||
.toMatch(
|
||||
/HttpClientXsrfModule = HttpClientXsrfModule_1 = .*__decorate.*\(\[\n\s*NgModule\(\{\n\s*providers: \[],\n\s*}\)\n\s*], HttpClientXsrfModule\);/);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -2160,5 +2160,62 @@ runInEachFileSystem(() => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getEndOfClass()', () => {
|
||||
it('should return the last static property of the class', () => {
|
||||
const testFile: TestFile = {
|
||||
name: _('/node_modules/test-package/some/file.js'),
|
||||
contents: `import {Directive, NgZone, Console} from '@angular/core';\n` +
|
||||
`export class SomeDirective {\n` +
|
||||
` constructor(zone, cons) {}\n` +
|
||||
` method() {}\n` +
|
||||
`}\n` +
|
||||
`SomeDirective.decorators = [\n` +
|
||||
` { type: Directive, args: [{ selector: '[a]' }] },\n` +
|
||||
` { type: OtherA }\n` +
|
||||
`];\n` +
|
||||
`SomeDirective.ctorParameters = () => [\n` +
|
||||
` { type: NgZone },\n` +
|
||||
` { type: Console }\n` +
|
||||
`];\n` +
|
||||
`callSomeFunction();\n` +
|
||||
`var value = 100;\n`
|
||||
};
|
||||
loadTestFiles([testFile]);
|
||||
const {program} = makeTestBundleProgram(testFile.name);
|
||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
const classSymbol = host.findClassSymbols(program.getSourceFile(testFile.name) !)[0];
|
||||
const endOfClass = host.getEndOfClass(classSymbol);
|
||||
expect(endOfClass.getText())
|
||||
.toEqual(
|
||||
`SomeDirective.ctorParameters = () => [\n` +
|
||||
` { type: NgZone },\n` +
|
||||
` { type: Console }\n` +
|
||||
`];`);
|
||||
});
|
||||
|
||||
it('should return the class declaration if there are no extra statements', () => {
|
||||
const testFile: TestFile = {
|
||||
name: _('/node_modules/test-package/some/file.js'),
|
||||
contents: `export class SomeDirective {\n` +
|
||||
` constructor(zone, cons) {}\n` +
|
||||
` method() {}\n` +
|
||||
`}\n` +
|
||||
`callSomeFunction();\n` +
|
||||
`var value = 100;\n`
|
||||
};
|
||||
loadTestFiles([testFile]);
|
||||
const {program} = makeTestBundleProgram(testFile.name);
|
||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
const classSymbol = host.findClassSymbols(program.getSourceFile(testFile.name) !)[0];
|
||||
const endOfClass = host.getEndOfClass(classSymbol);
|
||||
expect(endOfClass.getText())
|
||||
.toEqual(
|
||||
`export class SomeDirective {\n` +
|
||||
` constructor(zone, cons) {}\n` +
|
||||
` method() {}\n` +
|
||||
`}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -532,6 +532,19 @@ export { SomeDirective };
|
||||
expect(value).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getEndOfClass()', () => {
|
||||
it('should return the last statement related to the class', () => {
|
||||
const {program} = makeTestBundleProgram(_('/ngmodule.js'));
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
const classSymbol =
|
||||
host.findClassSymbols(program.getSourceFile(_('/ngmodule.js')) !)[0];
|
||||
const endOfClass = host.getEndOfClass(classSymbol);
|
||||
expect(endOfClass.getText())
|
||||
.toMatch(
|
||||
/HttpClientXsrfModule = HttpClientXsrfModule_1 = .*__decorate.*\(\[\n\s*NgModule\(\{\n\s*providers: \[],\n\s*}\)\n\s*], HttpClientXsrfModule\);/);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function findVariableDeclaration(
|
||||
|
@ -2530,5 +2530,20 @@ runInEachFileSystem(() => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getEndOfClass()', () => {
|
||||
it('should return the last static property of the class', () => {
|
||||
loadTestFiles([SOME_DIRECTIVE_FILE]);
|
||||
const {program} = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, program.getTypeChecker());
|
||||
const classSymbol =
|
||||
host.findClassSymbols(program.getSourceFile(SOME_DIRECTIVE_FILE.name) !)[0];
|
||||
const endOfClass = host.getEndOfClass(classSymbol);
|
||||
expect(endOfClass.getText()).toEqual(`SomeDirective.propDecorators = {
|
||||
"input1": [{ type: Input },],
|
||||
"input2": [{ type: Input },],
|
||||
};`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user