8000 fix(compiler-cli): do not drop non-Angular decorators when downleveli… · angular/angular@1c6cf8a · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit 1c6cf8a

Browse files
petebacondarwinmhevery
authored andcommitted
fix(compiler-cli): do not drop non-Angular decorators when downleveling (#39577)
There is a compiler transform that downlevels Angular class decorators to static properties so that metadata is available for JIT compilation. The transform was supposed to ignore non-Angular decorators but it was actually completely dropping decorators that did not conform to a very specific syntactic shape (i.e. the decorator was a simple identifier, or a namespaced identifier). This commit ensures that all non-Angular decorators are kepts as-is even if they are built using a syntax that the Angular compiler does not understand. Fixes #39574 PR Close #39577
1 parent 7bd0133 commit 1c6cf8a

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

packages/compiler-cli/src/transformers/downlevel_decorators_transform.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -538,12 +538,17 @@ export function getDownlevelDecoratorsTransform(
538538
}
539539
newMembers.push(ts.visitEachChild(member, decoratorDownlevelVisitor, context));
540540
}
541-
const decorators = host.getDecoratorsOfDeclaration(classDecl) || [];
541+
542+
// The `ReflectionHost.getDecoratorsOfDeclaration()` method will not return certain kinds of
543+
// decorators that will never be Angular decorators. So we cannot rely on it to capture all
544+
// the decorators that should be kept. Instead we start off with a set of the raw decorators
545+
// on the class, and only remove the ones that have been identified for downleveling.
546+
const decoratorsToKeep = new Set<ts.Decorator>(classDecl.decorators);
547+
const possibleAngularDecorators = host.getDecoratorsOfDeclaration(classDecl) || [];
542548

543549
let hasAngularDecorator = false;
544550
const decoratorsToLower = [];
545-
const decoratorsToKeep: ts.Decorator[] = [];
546-
for (const decorator of decorators) {
551+
for (const decorator of possibleAngularDecorators) {
547552
// We only deal with concrete nodes in TypeScript sources, so we don't
548553
// need to handle synthetically created decorators.
549554
const decoratorNode = decorator.node! as ts.Decorator;
@@ -557,8 +562,7 @@ export function getDownlevelDecoratorsTransform(
557562

558563
if (isNgDecorator && !skipClassDecorators) {
559564
decoratorsToLower.push(extractMetadataFromSingleDecorator(decoratorNode, diagnostics));
560-
} else {
561-
decoratorsToKeep.push(decoratorNode);
565+
decoratorsToKeep.delete(decoratorNode);
562566
}
563567
}
564568

@@ -581,8 +585,9 @@ export function getDownlevelDecoratorsTransform(
581585
ts.createNodeArray(newMembers, classDecl.members.hasTrailingComma), classDecl.members);
582586

583587
return ts.updateClassDeclaration(
584-
classDecl, decoratorsToKeep.length ? decoratorsToKeep : undefined, classDecl.modifiers,
585-
classDecl.name, classDecl.typeParameters, classDecl.heritageClauses, members);
588+
classDecl, decoratorsToKeep.size ? Array.from(decoratorsToKeep) : undefined,
589+
classDecl.modifiers, classDecl.name, classDecl.typeParameters, classDecl.heritageClauses,
590+
members);
586591
}
587592

588593
/**

packages/compiler-cli/test/transformers/downlevel_decorators_transform_spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,21 @@ describe('downlevel decorator transform', () => {
189189
expect(output).not.toContain('MyClass.decorators');
190190
});
191191

192+
it('should not downlevel non-Angular class decorators generated by a builder', () => {
193+
const {output} = transform(`
194+
@DecoratorBuilder().customClassDecorator
195+
export class MyClass {}
196+
`);
197+
198+
expect(diagnostics.length).toBe(0);
199+
expect(output).toContain(dedent`
200+
MyClass = tslib_1.__decorate([
201+
DecoratorBuilder().customClassDecorator
202+
], MyClass);
203+
`);
204+
expect(output).not.toContain('MyClass.decorators');
205+
});
206+
192207
it('should downlevel Angular-decorated class member', () => {
193208
const {output} = transform(`
194209
import {Input} from '@angular/core';

0 commit comments

Comments
 (0)
0