From c05967079298e1bcffdd95d99f43e40aa18e5fd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mis=CC=8Cko=20Hevery?= Date: Tue, 3 Apr 2018 11:25:55 -0700 Subject: [PATCH] feat(ivy): Add `outputs` support for `defineDirective` / `defineComponent` (#23168) PR Close #23168 --- .../compiler/src/render3/r3_view_compiler.ts | 18 ++-- .../r3_view_compiler_input_outputs_spec.ts | 86 +++++++++++++++++++ 2 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 packages/compiler/test/render3/r3_view_compiler_input_outputs_spec.ts diff --git a/packages/compiler/src/render3/r3_view_compiler.ts b/packages/compiler/src/render3/r3_view_compiler.ts index 49e1cf9eed..610cb3d31a 100644 --- a/packages/compiler/src/render3/r3_view_compiler.ts +++ b/packages/compiler/src/render3/r3_view_compiler.ts @@ -73,7 +73,10 @@ export function compileDirective( field('attributes', createHostAttributesArray(directive, outputCtx)); // e.g 'inputs: {a: 'a'}` - field('inputs', createInputsObject(directive, outputCtx)); + field('inputs', createMapObjectLiteral(directive.inputs, outputCtx)); + + // e.g 'outputs: {a: 'a'}` + field('outputs', createMapObjectLiteral(directive.outputs, outputCtx)); const className = identifierName(directive.type) !; className || error(`Cannot resolver the name of ${directive.type}`); @@ -193,7 +196,10 @@ export function compileComponent( } // e.g `inputs: {a: 'a'}` - field('inputs', createInputsObject(component, outputCtx)); + field('inputs', createMapObjectLiteral(component.inputs, outputCtx)); + + // e.g 'outputs: {a: 'a'}` + field('outputs', createMapObjectLiteral(component.outputs, outputCtx)); // e.g. `features: [NgOnChangesFeature(MyComponent)]` const features: o.Expression[] = []; @@ -1052,10 +1058,10 @@ function createHostBindingsFunction( return null; } -function createInputsObject( - directive: CompileDirectiveMetadata, outputCtx: OutputContext): o.Expression|null { - if (Object.getOwnPropertyNames(directive.inputs).length > 0) { - return outputCtx.constantPool.getConstLiteral(mapToExpression(directive.inputs)); +function createMapObjectLiteral( + keys: {[key: string]: string}, outputCtx: OutputContext): o.Expression|null { + if (Object.getOwnPropertyNames(keys).length > 0) { + return mapToExpression(keys); } return null; } diff --git a/packages/compiler/test/render3/r3_view_compiler_input_outputs_spec.ts b/packages/compiler/test/render3/r3_view_compiler_input_outputs_spec.ts new file mode 100644 index 0000000000..3761fc6907 --- /dev/null +++ b/packages/compiler/test/render3/r3_view_compiler_input_outputs_spec.ts @@ -0,0 +1,86 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {MockDirectory, setup} from '../aot/test_util'; +import {compile, expectEmit} from './mock_compile'; + +describe('compiler compliance: listen()', () => { + const angularFiles = setup({ + compileAngular: true, + compileAnimations: false, + compileCommon: true, + }); + + it('should create declare inputs/outputs', () => { + const files = { + app: { + 'spec.ts': ` + import {Component, Directive, NgModule, Input, Output} from '@angular/core'; + + @Component({ + selector: 'my-component', + template: \`\` + }) + export class MyComponent { + @Input() componentInput; + @Input('renamedComponentInput') originalComponentInput; + + @Output() componentOutput; + @Output('renamedComponentOutput') originalComponentOutput; + } + + @Directive({ + selector: '[my-directive]', + }) + export class MyDirective { + @Input() directiveInput; + @Input('renamedDirectiveInput') originalDirectiveInput; + + @Output() directiveOutput; + @Output('renamedDirectiveOutput') originalDirectiveOutput; + } + + @NgModule({declarations: [MyComponent, MyDirective]}) + export class MyModule {} + ` + } + }; + + // The template should look like this (where IDENT is a wild card for an identifier): + const template = ` + static ngComponentDef = i0.ɵdefineComponent({ + … + inputs:{ + componentInput: 'componentInput', + originalComponentInput: 'renamedComponentInput' + }, + outputs: { + componentOutput: 'componentOutput', + originalComponentOutput: 'renamedComponentOutput' + } + }); + … + static ngDirectiveDef = i0.ɵdefineDirective({ + … + inputs:{ + directiveInput: 'directiveInput', + originalDirectiveInput: 'renamedDirectiveInput' + }, + outputs: { + directiveOutput: 'directiveOutput', + originalDirectiveOutput: 'renamedDirectiveOutput' + } + });`; + + + const result = compile(files, angularFiles); + + expectEmit(result.source, template, 'Incorrect template'); + }); + +}); \ No newline at end of file