fix(ivy): prevent ngcc from inadvertently dropping Ivy definitions (#27159)
A surprising interaction with the MagicString library caused inserted Ivy definitions to be dropped during the removal of decorators, iff all decorators on the class could be removed. In that case, the removal location corresponds with the exact location where Ivy definitions were inserted into. This commit moves the removal of decorators to occur before Ivy definitions are inserted. This effectively avoids the problem, as later inserted text fragments will be retained by MagicString. PR Close #27159
This commit is contained in:
@ -315,10 +315,12 @@ SOME DEFINITION TEXT
|
||||
const decoratorsToRemove = new Map<ts.Node, ts.Node[]>();
|
||||
decoratorsToRemove.set(decorator.node.parent !, [decorator.node]);
|
||||
renderer.removeDecorators(output, decoratorsToRemove);
|
||||
renderer.addDefinitions(output, compiledClass, 'SOME DEFINITION TEXT');
|
||||
expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[a]' }] },`);
|
||||
expect(output.toString()).toContain(`{ type: OtherA }`);
|
||||
expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[b]' }] }`);
|
||||
expect(output.toString()).toContain(`{ type: OtherB }`);
|
||||
expect(output.toString()).toContain(`function C() {}\nSOME DEFINITION TEXT\n return C;`);
|
||||
expect(output.toString()).not.toContain(`C.decorators = [
|
||||
{ type: Directive, args: [{ selector: '[c]' }] },
|
||||
];`);
|
||||
|
@ -14,7 +14,7 @@ import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registr
|
||||
import {PrivateDeclarationsAnalyzer} from '../../src/analysis/private_declarations_analyzer';
|
||||
import {SwitchMarkerAnalyzer} from '../../src/analysis/switch_marker_analyzer';
|
||||
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
||||
import {Renderer} from '../../src/rendering/renderer';
|
||||
import {RedundantDecoratorMap, Renderer} from '../../src/rendering/renderer';
|
||||
import {EntryPointBundle} from '../../src/packages/entry_point_bundle';
|
||||
import {makeTestEntryPointBundle} from '../helpers/utils';
|
||||
|
||||
@ -37,7 +37,7 @@ class TestRenderer extends Renderer {
|
||||
addDefinitions(output: MagicString, compiledClass: CompiledClass, definitions: string) {
|
||||
output.prepend('\n// ADD DEFINITIONS\n');
|
||||
}
|
||||
removeDecorators(output: MagicString, decoratorsToRemove: Map<ts.Node, ts.Node[]>) {
|
||||
removeDecorators(output: MagicString, decoratorsToRemove: RedundantDecoratorMap) {
|
||||
output.prepend('\n// REMOVE DECORATORS\n');
|
||||
}
|
||||
rewriteSwitchableDeclarations(output: MagicString, sourceFile: ts.SourceFile): void {
|
||||
@ -97,7 +97,7 @@ describe('Renderer', () => {
|
||||
});
|
||||
|
||||
const RENDERED_CONTENTS =
|
||||
`\n// ADD EXPORTS\n\n// REMOVE DECORATORS\n\n// ADD IMPORTS\n\n// ADD CONSTANTS\n\n// ADD DEFINITIONS\n` +
|
||||
`\n// ADD EXPORTS\n\n// ADD IMPORTS\n\n// ADD CONSTANTS\n\n// ADD DEFINITIONS\n\n// REMOVE DECORATORS\n` +
|
||||
INPUT_PROGRAM.contents;
|
||||
|
||||
const OUTPUT_PROGRAM_MAP = fromObject({
|
||||
|
Reference in New Issue
Block a user