From eb74a9693507415e191cd803623521e04d0c79c3 Mon Sep 17 00:00:00 2001 From: JoostK Date: Sat, 6 Mar 2021 15:50:37 +0100 Subject: [PATCH] refactor(compiler-cli): separate used components from used directives in partial declaration (#41104) The partial declaration of a component includes the list of directives that are used in its template, including some metadata of the directive which can be used during actual compilation of the component. Used components are currently part of this list, as components are also directives. This commit splits the used components into a dedicate property in the partial declaration, which allows for template compilation to optimize the generated code for components. PR Close #41104 --- .../partial_component_linker_1.ts | 60 +++++++++-------- .../GOLDEN_PARTIAL.js | 4 +- .../content_projection/GOLDEN_PARTIAL.js | 6 +- .../lifecycle_hooks/GOLDEN_PARTIAL.js | 2 +- .../queries/GOLDEN_PARTIAL.js | 4 +- .../value_composition/GOLDEN_PARTIAL.js | 10 +-- .../elements/GOLDEN_PARTIAL.js | 2 +- .../r3_view_compiler/GOLDEN_PARTIAL.js | 2 +- .../attribute_bindings/GOLDEN_PARTIAL.js | 2 +- .../property_bindings/GOLDEN_PARTIAL.js | 2 +- .../GOLDEN_PARTIAL.js | 4 +- packages/compiler/src/render3/partial/api.ts | 64 +++++++++++-------- .../compiler/src/render3/partial/component.ts | 18 ++++-- 13 files changed, 103 insertions(+), 77 deletions(-) diff --git a/packages/compiler-cli/linker/src/file_linker/partial_linkers/partial_component_linker_1.ts b/packages/compiler-cli/linker/src/file_linker/partial_linkers/partial_component_linker_1.ts index 014ac0024d..d2d0d09f00 100644 --- a/packages/compiler-cli/linker/src/file_linker/partial_linkers/partial_component_linker_1.ts +++ b/packages/compiler-cli/linker/src/file_linker/partial_linkers/partial_component_linker_1.ts @@ -5,7 +5,7 @@ * 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 {compileComponentFromMetadata, ConstantPool, DeclarationListEmitMode, DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig, makeBindingParser, parseTemplate, R3ComponentMetadata, R3DeclareComponentMetadata, R3PartialDeclaration, R3UsedDirectiveMetadata} from '@angular/compiler'; +import {compileComponentFromMetadata, ConstantPool, DeclarationListEmitMode, DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig, makeBindingParser, parseTemplate, R3ComponentMetadata, R3DeclareComponentMetadata, R3DeclareUsedDirectiveMetadata, R3PartialDeclaration, R3UsedDirectiveMetadata} from '@angular/compiler'; import {ChangeDetectionStrategy, ViewEncapsulation} from '@angular/compiler/src/core'; import * as o from '@angular/compiler/src/output/output_ast'; @@ -74,34 +74,42 @@ export class PartialComponentLinkerVersion1 implements let declarationListEmitMode = DeclarationListEmitMode.Direct; - let directives: R3UsedDirectiveMetadata[] = []; - if (metaObj.has('directives')) { - directives = metaObj.getArray('directives').map(directive => { - const directiveExpr = directive.getObject(); - const type = directiveExpr.getValue('type'); - const selector = directiveExpr.getString('selector'); + const collectUsedDirectives = + (directives: AstValue[]) => { + return directives.map(directive => { + const directiveExpr = directive.getObject(); + const type = directiveExpr.getValue('type'); + const selector = directiveExpr.getString('selector'); - let typeExpr = type.getOpaque(); - const forwardRefType = extractForwardRef(type); - if (forwardRefType !== null) { - typeExpr = forwardRefType; - declarationListEmitMode = DeclarationListEmitMode.Closure; - } + let typeExpr = type.getOpaque(); + const forwardRefType = extractForwardRef(type); + if (forwardRefType !== null) { + typeExpr = forwardRefType; + declarationListEmitMode = DeclarationListEmitMode.Closure; + } - return { - type: typeExpr, - selector: selector, - inputs: directiveExpr.has('inputs') ? - directiveExpr.getArray('inputs').map(input => input.getString()) : - [], - outputs: directiveExpr.has('outputs') ? - directiveExpr.getArray('outputs').map(input => input.getString()) : - [], - exportAs: directiveExpr.has('exportAs') ? - directiveExpr.getArray('exportAs').map(exportAs => exportAs.getString()) : - null, + return { + type: typeExpr, + selector: selector, + inputs: directiveExpr.has('inputs') ? + directiveExpr.getArray('inputs').map(input => input.getString()) : + [], + outputs: directiveExpr.has('outputs') ? + directiveExpr.getArray('outputs').map(input => input.getString()) : + [], + exportAs: directiveExpr.has('exportAs') ? + directiveExpr.getArray('exportAs').map(exportAs => exportAs.getString()) : + null, + }; + }); }; - }); + + let directives: R3UsedDirectiveMetadata[] = []; + if (metaObj.has('components')) { + directives.push(...collectUsedDirectives(metaObj.getArray('components'))); + } + if (metaObj.has('directives')) { + directives.push(...collectUsedDirectives(metaObj.getArray('directives'))); } let pipes = new Map(); diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/GOLDEN_PARTIAL.js index faba87db8b..8af31a6ed5 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/GOLDEN_PARTIAL.js @@ -181,7 +181,7 @@ SomeComp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: export class MyApp { } MyApp.ɵfac = function MyApp_Factory(t) { return new (t || MyApp)(); }; -MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "ng-component", ngImport: i0, template: '', isInline: true, directives: [{ type: SomeComp, selector: "some-comp", inputs: ["prop", "otherProp"] }] }); +MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "ng-component", ngImport: i0, template: '', isInline: true, components: [{ type: SomeComp, selector: "some-comp", inputs: ["prop", "otherProp"] }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyApp, [{ type: Component, args: [{ template: '' }] @@ -236,7 +236,7 @@ SomeComp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: export class MyApp { } MyApp.ɵfac = function MyApp_Factory(t) { return new (t || MyApp)(); }; -MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "ng-component", ngImport: i0, template: '', isInline: true, directives: [{ type: SomeComp, selector: "some-comp", inputs: ["prop", "otherProp"] }] }); +MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "ng-component", ngImport: i0, template: '', isInline: true, components: [{ type: SomeComp, selector: "some-comp", inputs: ["prop", "otherProp"] }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyApp, [{ type: Component, args: [{ template: '' }] diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/content_projection/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/content_projection/GOLDEN_PARTIAL.js index 0c1d56d7dc..b79831460d 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/content_projection/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/content_projection/GOLDEN_PARTIAL.js @@ -29,7 +29,7 @@ ComplexComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER export class MyApp { } MyApp.ɵfac = function MyApp_Factory(t) { return new (t || MyApp)(); }; -MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: 'content ', isInline: true, directives: [{ type: SimpleComponent, selector: "simple" }, { type: ComplexComponent, selector: "complex" }] }); +MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: 'content ', isInline: true, components: [{ type: SimpleComponent, selector: "simple" }, { type: ComplexComponent, selector: "complex" }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyApp, [{ type: Component, args: [{ selector: 'my-app', template: 'content ' }] @@ -224,7 +224,7 @@ SimpleComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER" export class MyApp { } MyApp.ɵfac = function MyApp_Factory(t) { return new (t || MyApp)(); }; -MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: '

', isInline: true, directives: [{ type: SimpleComponent, selector: "simple" }] }); +MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: '

', isInline: true, components: [{ type: SimpleComponent, selector: "simple" }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyApp, [{ type: Component, args: [{ selector: 'my-app', template: '

' }] @@ -273,7 +273,7 @@ SimpleComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER" export class MyApp { } MyApp.ɵfac = function MyApp_Factory(t) { return new (t || MyApp)(); }; -MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: '

', isInline: true, directives: [{ type: SimpleComponent, selector: "simple" }] }); +MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: '

', isInline: true, components: [{ type: SimpleComponent, selector: "simple" }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyApp, [{ type: Component, args: [{ selector: 'my-app', template: '

' }] diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/lifecycle_hooks/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/lifecycle_hooks/GOLDEN_PARTIAL.js index 3bc72ebaa5..3f5de1ea6f 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/lifecycle_hooks/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/lifecycle_hooks/GOLDEN_PARTIAL.js @@ -211,7 +211,7 @@ SimpleLayout.ɵfac = function SimpleLayout_Factory(t) { return new (t || SimpleL SimpleLayout.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: SimpleLayout, selector: "simple-layout", ngImport: i0, template: ` - `, isInline: true, directives: [{ type: LifecycleComp, selector: "lifecycle-comp", inputs: ["name"] }] }); + `, isInline: true, components: [{ type: LifecycleComp, selector: "lifecycle-comp", inputs: ["name"] }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SimpleLayout, [{ type: Component, args: [{ diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/GOLDEN_PARTIAL.js index efd702fb5e..b7cbcb9b75 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/GOLDEN_PARTIAL.js @@ -365,7 +365,7 @@ MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: My
- `, isInline: true, directives: [{ type: i0.forwardRef(function () { return ContentQueryComponent; }), selector: "content-query-component" }, { type: i0.forwardRef(function () { return SomeDirective; }), selector: "[someDir]" }] }); + `, isInline: true, components: [{ type: i0.forwardRef(function () { return ContentQueryComponent; }), selector: "content-query-component" }], directives: [{ type: i0.forwardRef(function () { return SomeDirective; }), selector: "[someDir]" }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyApp, [{ type: Component, args: [{ @@ -524,7 +524,7 @@ MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: My
- `, isInline: true, directives: [{ type: i0.forwardRef(function () { return ContentQueryComponent; }), selector: "content-query-component" }, { type: i0.forwardRef(function () { return SomeDirective; }), selector: "[someDir]" }] }); + `, isInline: true, components: [{ type: i0.forwardRef(function () { return ContentQueryComponent; }), selector: "content-query-component" }], directives: [{ type: i0.forwardRef(function () { return SomeDirective; }), selector: "[someDir]" }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyApp, [{ type: Component, args: [{ diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/value_composition/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/value_composition/GOLDEN_PARTIAL.js index 80010dc803..b47646b927 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/value_composition/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/value_composition/GOLDEN_PARTIAL.js @@ -22,7 +22,7 @@ SomeDirective.ɵdir = i0.ɵɵngDeclareDirective({ version: "0.0.0-PLACEHOLDER", export class MyComponent { } MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); }; -MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyComponent, selector: "my-component", ngImport: i0, template: '!', isInline: true, directives: [{ type: ChildComponent, selector: "child" }, { type: SomeDirective, selector: "[some-directive]" }] }); +MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyComponent, selector: "my-component", ngImport: i0, template: '!', isInline: true, components: [{ type: ChildComponent, selector: "child" }], directives: [{ type: SomeDirective, selector: "[some-directive]" }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyComponent, [{ type: Component, args: [{ selector: 'my-component', template: '!' }] @@ -329,7 +329,7 @@ export class MyApp { MyApp.ɵfac = function MyApp_Factory(t) { return new (t || MyApp)(); }; MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: ` -`, isInline: true, directives: [{ type: MyComp, selector: "my-comp", inputs: ["names"] }] }); +`, isInline: true, components: [{ type: MyComp, selector: "my-comp", inputs: ["names"] }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyApp, [{ type: Component, args: [{ @@ -428,7 +428,7 @@ MyApp.ɵfac = function MyApp_Factory(t) { return new (t || MyApp)(); }; MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: ` -`, isInline: true, directives: [{ type: MyComp, selector: "my-comp", inputs: ["names"] }] }); +`, isInline: true, components: [{ type: MyComp, selector: "my-comp", inputs: ["names"] }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyApp, [{ type: Component, args: [{ @@ -509,7 +509,7 @@ export class MyApp { MyApp.ɵfac = function MyApp_Factory(t) { return new (t || MyApp)(); }; MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: ` -`, isInline: true, directives: [{ type: ObjectComp, selector: "object-comp", inputs: ["config"] }] }); +`, isInline: true, components: [{ type: ObjectComp, selector: "object-comp", inputs: ["config"] }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyApp, [{ type: Component, args: [{ @@ -587,7 +587,7 @@ MyApp.ɵfac = function MyApp_Factory(t) { return new (t || MyApp)(); }; MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: ` -`, isInline: true, directives: [{ type: NestedComp, selector: "nested-comp", inputs: ["config"] }] }); +`, isInline: true, components: [{ type: NestedComp, selector: "nested-comp", inputs: ["config"] }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyApp, [{ type: Component, args: [{ diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/elements/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/elements/GOLDEN_PARTIAL.js index 1803fcba88..7f38d8cf9d 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/elements/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/elements/GOLDEN_PARTIAL.js @@ -62,7 +62,7 @@ InfinityCmp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", ty export class MyComponent { } MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); }; -MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyComponent, selector: "my-component", ngImport: i0, template: '

test

', isInline: true, directives: [{ type: MathCmp, selector: "math" }, { type: InfinityCmp, selector: "infinity" }] }); +MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyComponent, selector: "my-component", ngImport: i0, template: '

test

', isInline: true, components: [{ type: MathCmp, selector: "math" }, { type: InfinityCmp, selector: "infinity" }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyComponent, [{ type: Component, args: [{ diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/GOLDEN_PARTIAL.js index b431ff126e..715b3fc61a 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/GOLDEN_PARTIAL.js @@ -9,7 +9,7 @@ export class MyApp { } } MyApp.ɵfac = function MyApp_Factory(t) { return new (t || MyApp)(); }; -MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: '', isInline: true, directives: [{ type: i0.forwardRef(function () { return TodoComponent; }), selector: "todo", inputs: ["data"] }] }); +MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: '', isInline: true, components: [{ type: i0.forwardRef(function () { return TodoComponent; }), selector: "todo", inputs: ["data"] }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyApp, [{ type: Component, args: [{ selector: 'my-app', template: '' }] diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/attribute_bindings/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/attribute_bindings/GOLDEN_PARTIAL.js index 3918059f50..27a2235efd 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/attribute_bindings/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/attribute_bindings/GOLDEN_PARTIAL.js @@ -158,7 +158,7 @@ MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", ty - `, isInline: true, directives: [{ type: CustomEl, selector: "custom-element" }] }); + `, isInline: true, components: [{ type: CustomEl, selector: "custom-element" }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyComponent, [{ type: Component, args: [{ diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/property_bindings/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/property_bindings/GOLDEN_PARTIAL.js index b56b395681..1be3bd8735 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/property_bindings/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/property_bindings/GOLDEN_PARTIAL.js @@ -519,7 +519,7 @@ MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", ty - `, isInline: true, directives: [{ type: SpanDir, selector: "span", inputs: ["someProp"] }, { type: CustomEl, selector: "custom-element", inputs: ["prop", "otherProp"] }] }); + `, isInline: true, components: [{ type: CustomEl, selector: "custom-element", inputs: ["prop", "otherProp"] }], directives: [{ type: SpanDir, selector: "span", inputs: ["someProp"] }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyComponent, [{ type: Component, args: [{ diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_listener/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_listener/GOLDEN_PARTIAL.js index e3813aacd0..f96b4a7bca 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_listener/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_listener/GOLDEN_PARTIAL.js @@ -54,7 +54,7 @@ export class MyComponent { onClick(event) { } } MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); }; -MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyComponent, selector: "my-component", ngImport: i0, template: ``, isInline: true, directives: [{ type: MyApp, selector: "my-app" }] }); +MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyComponent, selector: "my-component", ngImport: i0, template: ``, isInline: true, components: [{ type: MyApp, selector: "my-app" }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyComponent, [{ type: Component, args: [{ selector: 'my-component', template: `` }] @@ -268,7 +268,7 @@ MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyCompone MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyComponent, selector: "my-component", ngImport: i0, template: `
- `, isInline: true, directives: [{ type: SomeComp, selector: "some-comp", outputs: ["update", "delete"] }] }); + `, isInline: true, components: [{ type: SomeComp, selector: "some-comp", outputs: ["update", "delete"] }] }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyComponent, [{ type: Component, args: [{ diff --git a/packages/compiler/src/render3/partial/api.ts b/packages/compiler/src/render3/partial/api.ts index fabc62dd77..fa9e4d5895 100644 --- a/packages/compiler/src/render3/partial/api.ts +++ b/packages/compiler/src/render3/partial/api.ts @@ -133,39 +133,21 @@ export interface R3DeclareComponentMetadata extends R3DeclareDirectiveMetadata { */ styles?: string[]; + /** + * List of components which matched in the template, including sufficient + * metadata for each directive to attribute bindings and references within + * the template to each directive specifically, if the runtime instructions + * support this. + */ + components?: R3DeclareUsedDirectiveMetadata[]; + /** * List of directives which matched in the template, including sufficient * metadata for each directive to attribute bindings and references within * the template to each directive specifically, if the runtime instructions * support this. */ - directives?: { - /** - * Selector of the directive. - */ - selector: string; - - /** - * Reference to the directive class (possibly a forward reference wrapped in a `forwardRef` - * invocation). - */ - type: o.Expression | (() => o.Expression); - - /** - * Property names of the directive's inputs. - */ - inputs?: string[]; - - /** - * Event names of the directive's outputs. - */ - outputs?: string[]; - - /** - * Names by which this directive exports itself for references. - */ - exportAs?: string[]; - }[]; + directives?: R3DeclareUsedDirectiveMetadata[]; /** * A map of pipe names to an expression referencing the pipe type (possibly a forward reference @@ -206,6 +188,34 @@ export interface R3DeclareComponentMetadata extends R3DeclareDirectiveMetadata { preserveWhitespaces?: boolean; } +export interface R3DeclareUsedDirectiveMetadata { + /** + * Selector of the directive. + */ + selector: string; + + /** + * Reference to the directive class (possibly a forward reference wrapped in a `forwardRef` + * invocation). + */ + type: o.Expression|(() => o.Expression); + + /** + * Property names of the directive's inputs. + */ + inputs?: string[]; + + /** + * Event names of the directive's outputs. + */ + outputs?: string[]; + + /** + * Names by which this directive exports itself for references. + */ + exportAs?: string[]; +} + export interface R3DeclareQueryMetadata { /** * Name of the property on the class to update with query results. diff --git a/packages/compiler/src/render3/partial/component.ts b/packages/compiler/src/render3/partial/component.ts index 74080d082b..d54f1e7b84 100644 --- a/packages/compiler/src/render3/partial/component.ts +++ b/packages/compiler/src/render3/partial/component.ts @@ -16,7 +16,7 @@ import {createComponentType} from '../view/compiler'; import {ParsedTemplate} from '../view/template'; import {DefinitionMap} from '../view/util'; -import {R3DeclareComponentMetadata} from './api'; +import {R3DeclareComponentMetadata, R3DeclareUsedDirectiveMetadata} from './api'; import {createDirectiveDefinitionMap} from './directive'; import {toOptionalLiteralArray} from './util'; @@ -48,7 +48,12 @@ export function createComponentDefinitionMap(meta: R3ComponentMetadata, template } definitionMap.set('styles', toOptionalLiteralArray(meta.styles, o.literal)); - definitionMap.set('directives', compileUsedDirectiveMetadata(meta)); + definitionMap.set( + 'components', + compileUsedDirectiveMetadata(meta, directive => directive.isComponent === true)); + definitionMap.set( + 'directives', + compileUsedDirectiveMetadata(meta, directive => directive.isComponent !== true)); definitionMap.set('pipes', compileUsedPipeMetadata(meta)); definitionMap.set('viewProviders', meta.viewProviders); definitionMap.set('animations', meta.animations); @@ -119,13 +124,16 @@ function computeEndLocation(file: ParseSourceFile, contents: string): ParseLocat * Compiles the directives as registered in the component metadata into an array literal of the * individual directives. If the component does not use any directives, then null is returned. */ -function compileUsedDirectiveMetadata(meta: R3ComponentMetadata): o.LiteralArrayExpr|null { +function compileUsedDirectiveMetadata( + meta: R3ComponentMetadata, + predicate: (directive: R3UsedDirectiveMetadata) => boolean): o.LiteralArrayExpr|null { const wrapType = meta.declarationListEmitMode !== DeclarationListEmitMode.Direct ? generateForwardRef : (expr: o.Expression) => expr; - return toOptionalLiteralArray(meta.directives, directive => { - const dirMeta = new DefinitionMap(); + const directives = meta.directives.filter(predicate); + return toOptionalLiteralArray(directives, directive => { + const dirMeta = new DefinitionMap(); dirMeta.set('type', wrapType(directive.type)); dirMeta.set('selector', o.literal(directive.selector)); dirMeta.set('inputs', toOptionalLiteralArray(directive.inputs, o.literal));