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}; return {analysis};
} }
compile(node: ts.ClassDeclaration, analysis: R3DirectiveMetadata): CompileResult { compile(node: ts.ClassDeclaration, analysis: R3DirectiveMetadata, pool: ConstantPool):
const pool = new ConstantPool(); CompileResult {
const res = compileDirectiveFromMetadata(analysis, pool, makeBindingParser()); const res = compileDirectiveFromMetadata(analysis, pool, makeBindingParser());
return { return {
name: 'ngDirectiveDef', name: 'ngDirectiveDef',
initializer: res.expression, initializer: res.expression,
statements: pool.statements, statements: res.statements,
type: res.type, type: res.type,
}; };
} }

View File

@ -722,6 +722,29 @@ describe('ngtsc behavioral tests', () => {
.toContain('function GrandChild_Factory(t) { return new (t || GrandChild)(); }'); .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', it('should wrap "directives" in component metadata in a closure when forward references are present',
() => { () => {
writeConfig(); writeConfig();