fix(ivy): ngtsc directive compilation should use shared ConstantPool (#25620)

This fixes a bug in ngtsc where each @Directive was compiled using a
separate ConstantPool. This resulted in two issues:

* Directive constants were not shared across the file
* Extra statements from directive compilation were dropped instead of
added to the file

This commit fixes both issues and adds a test to verify @Directive is
working properly.

PR Close #25620
This commit is contained in:
Alex Rickabaugh 2018-08-22 11:37:07 -07:00 committed by Matias Niemelä
parent 22d58fc89b
commit eb1fe19088
2 changed files with 26 additions and 3 deletions

View File

@ -45,13 +45,13 @@ export class DirectiveDecoratorHandler implements DecoratorHandler<R3DirectiveMe
return {analysis};
}
compile(node: ts.ClassDeclaration, analysis: R3DirectiveMetadata): CompileResult {
const pool = new ConstantPool();
compile(node: ts.ClassDeclaration, analysis: R3DirectiveMetadata, pool: ConstantPool):
CompileResult {
const res = compileDirectiveFromMetadata(analysis, pool, makeBindingParser());
return {
name: 'ngDirectiveDef',
initializer: res.expression,
statements: pool.statements,
statements: res.statements,
type: res.type,
};
}

View File

@ -722,6 +722,29 @@ describe('ngtsc behavioral tests', () => {
.toContain('function GrandChild_Factory(t) { return new (t || GrandChild)(); }');
});
it('generates base factories for directives', () => {
writeConfig();
write(`test.ts`, `
import {Directive} from '@angular/core';
class Base {}
@Directive({
selector: '[test]',
})
class Dir extends Base {
}
`);
const exitCode = main(['-p', basePath], errorSpy);
expect(errorSpy).not.toHaveBeenCalled();
expect(exitCode).toBe(0);
const jsContents = getContents('test.js');
expect(jsContents).toContain('var ɵDir_BaseFactory = i0.ɵgetInheritedFactory(Dir)');
});
it('should wrap "directives" in component metadata in a closure when forward references are present',
() => {
writeConfig();