
For abstract directives, i.e. directives without a selector, it may happen that their constructor is called explicitly from a subclass, hence its parameters are not required to be valid for Angular's DI purposes. Prior to this commit however, having an abstract directive with a constructor that has parameters that are not eligible for Angular's DI would produce a compilation error. A similar scenario may occur for `@Injectable`s, where an explicit `use*` definition allows for the constructor to be irrelevant. For example, the situation where `useFactory` is specified allows for the constructor to be called explicitly with any value, so its constructor parameters are not required to be valid. For `@Injectable`s this is handled by generating a DI factory function that throws. This commit implements the same solution for abstract directives, such that a compilation error is avoided while still producing an error at runtime if the type is instantiated implicitly by Angular's DI mechanism. Fixes #32981 PR Close #32987
277 lines
7.3 KiB
TypeScript
277 lines
7.3 KiB
TypeScript
/**
|
|
* @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 {ChangeDetectionStrategy, ViewEncapsulation} from '../../core';
|
|
import {InterpolationConfig} from '../../ml_parser/interpolation_config';
|
|
import * as o from '../../output/output_ast';
|
|
import {ParseSourceSpan} from '../../parse_util';
|
|
import * as t from '../r3_ast';
|
|
import {R3DependencyMetadata} from '../r3_factory';
|
|
|
|
|
|
/**
|
|
* Information needed to compile a directive for the render3 runtime.
|
|
*/
|
|
export interface R3DirectiveMetadata {
|
|
/**
|
|
* Name of the directive type.
|
|
*/
|
|
name: string;
|
|
|
|
/**
|
|
* An expression representing a reference to the directive itself.
|
|
*/
|
|
type: o.Expression;
|
|
|
|
/**
|
|
* Number of generic type parameters of the type itself.
|
|
*/
|
|
typeArgumentCount: number;
|
|
|
|
/**
|
|
* A source span for the directive type.
|
|
*/
|
|
typeSourceSpan: ParseSourceSpan;
|
|
|
|
/**
|
|
* Dependencies of the directive's constructor.
|
|
*/
|
|
deps: R3DependencyMetadata[]|'invalid'|null;
|
|
|
|
/**
|
|
* Unparsed selector of the directive, or `null` if there was no selector.
|
|
*/
|
|
selector: string|null;
|
|
|
|
/**
|
|
* Information about the content queries made by the directive.
|
|
*/
|
|
queries: R3QueryMetadata[];
|
|
|
|
/**
|
|
* Information about the view queries made by the directive.
|
|
*/
|
|
viewQueries: R3QueryMetadata[];
|
|
|
|
/**
|
|
* Mappings indicating how the directive interacts with its host element (host bindings,
|
|
* listeners, etc).
|
|
*/
|
|
host: R3HostMetadata;
|
|
|
|
/**
|
|
* Information about usage of specific lifecycle events which require special treatment in the
|
|
* code generator.
|
|
*/
|
|
lifecycle: {
|
|
/**
|
|
* Whether the directive uses NgOnChanges.
|
|
*/
|
|
usesOnChanges: boolean;
|
|
};
|
|
|
|
/**
|
|
* A mapping of input field names to the property names.
|
|
*/
|
|
inputs: {[field: string]: string | [string, string]};
|
|
|
|
/**
|
|
* A mapping of output field names to the property names.
|
|
*/
|
|
outputs: {[field: string]: string};
|
|
|
|
/**
|
|
* Whether or not the component or directive inherits from another class
|
|
*/
|
|
usesInheritance: boolean;
|
|
|
|
/**
|
|
* Whether or not the component or directive inherits its entire decorator from its base class.
|
|
*/
|
|
fullInheritance: boolean;
|
|
|
|
/**
|
|
* Reference name under which to export the directive's type in a template,
|
|
* if any.
|
|
*/
|
|
exportAs: string[]|null;
|
|
|
|
/**
|
|
* The list of providers defined in the directive.
|
|
*/
|
|
providers: o.Expression|null;
|
|
}
|
|
|
|
/**
|
|
* Information needed to compile a component for the render3 runtime.
|
|
*/
|
|
export interface R3ComponentMetadata extends R3DirectiveMetadata {
|
|
/**
|
|
* Information about the component's template.
|
|
*/
|
|
template: {
|
|
/**
|
|
* Parsed nodes of the template.
|
|
*/
|
|
nodes: t.Node[];
|
|
};
|
|
|
|
/**
|
|
* A map of pipe names to an expression referencing the pipe type which are in the scope of the
|
|
* compilation.
|
|
*/
|
|
pipes: Map<string, o.Expression>;
|
|
|
|
/**
|
|
* A list of directive selectors and an expression referencing the directive type which are in the
|
|
* scope of the compilation.
|
|
*/
|
|
directives: {selector: string, expression: o.Expression}[];
|
|
|
|
/**
|
|
* Whether to wrap the 'directives' and/or `pipes` array, if one is generated, in a closure.
|
|
*
|
|
* This is done when the directives or pipes contain forward references.
|
|
*/
|
|
wrapDirectivesAndPipesInClosure: boolean;
|
|
|
|
/**
|
|
* A collection of styling data that will be applied and scoped to the component.
|
|
*/
|
|
styles: string[];
|
|
|
|
/**
|
|
* An encapsulation policy for the template and CSS styles. One of:
|
|
* - `ViewEncapsulation.Native`: Use shadow roots. This works only if natively available on the
|
|
* platform (note that this is marked the as the "deprecated shadow DOM" as of Angular v6.1.
|
|
* - `ViewEncapsulation.Emulated`: Use shimmed CSS that emulates the native behavior.
|
|
* - `ViewEncapsulation.None`: Use global CSS without any encapsulation.
|
|
* - `ViewEncapsulation.ShadowDom`: Use the latest ShadowDOM API to natively encapsulate styles
|
|
* into a shadow root.
|
|
*/
|
|
encapsulation: ViewEncapsulation;
|
|
|
|
/**
|
|
* A collection of animation triggers that will be used in the component template.
|
|
*/
|
|
animations: o.Expression|null;
|
|
|
|
/**
|
|
* The list of view providers defined in the component.
|
|
*/
|
|
viewProviders: o.Expression|null;
|
|
|
|
/**
|
|
* Path to the .ts file in which this template's generated code will be included, relative to
|
|
* the compilation root. This will be used to generate identifiers that need to be globally
|
|
* unique in certain contexts (such as g3).
|
|
*/
|
|
relativeContextFilePath: string;
|
|
|
|
/**
|
|
* Whether translation variable name should contain external message id
|
|
* (used by Closure Compiler's output of `goog.getMsg` for transition period).
|
|
*/
|
|
i18nUseExternalIds: boolean;
|
|
|
|
/**
|
|
* Overrides the default interpolation start and end delimiters ({{ and }}).
|
|
*/
|
|
interpolation: InterpolationConfig;
|
|
|
|
/**
|
|
* Strategy used for detecting changes in the component.
|
|
*/
|
|
changeDetection?: ChangeDetectionStrategy;
|
|
}
|
|
|
|
/**
|
|
* Information needed to compile a query (view or content).
|
|
*/
|
|
export interface R3QueryMetadata {
|
|
/**
|
|
* Name of the property on the class to update with query results.
|
|
*/
|
|
propertyName: string;
|
|
|
|
/**
|
|
* Whether to read only the first matching result, or an array of results.
|
|
*/
|
|
first: boolean;
|
|
|
|
/**
|
|
* Either an expression representing a type for the query predicate, or a set of string selectors.
|
|
*/
|
|
predicate: o.Expression|string[];
|
|
|
|
/**
|
|
* Whether to include only direct children or all descendants.
|
|
*/
|
|
descendants: boolean;
|
|
|
|
/**
|
|
* An expression representing a type to read from each matched node, or null if the default value
|
|
* for a given node is to be returned.
|
|
*/
|
|
read: o.Expression|null;
|
|
|
|
/**
|
|
* Whether or not this query should collect only static results.
|
|
*
|
|
* If static is true, the query's results will be set on the component after nodes are created,
|
|
* but before change detection runs. This means that any results that relied upon change detection
|
|
* to run (e.g. results inside *ngIf or *ngFor views) will not be collected. Query results are
|
|
* available in the ngOnInit hook.
|
|
*
|
|
* If static is false, the query's results will be set on the component after change detection
|
|
* runs. This means that the query results can contain nodes inside *ngIf or *ngFor views, but
|
|
* the results will not be available in the ngOnInit hook (only in the ngAfterContentInit for
|
|
* content hooks and ngAfterViewInit for view hooks).
|
|
*/
|
|
static: boolean;
|
|
}
|
|
|
|
/**
|
|
* Output of render3 directive compilation.
|
|
*/
|
|
export interface R3DirectiveDef {
|
|
expression: o.Expression;
|
|
type: o.Type;
|
|
}
|
|
|
|
/**
|
|
* Output of render3 component compilation.
|
|
*/
|
|
export interface R3ComponentDef {
|
|
expression: o.Expression;
|
|
type: o.Type;
|
|
}
|
|
|
|
/**
|
|
* Mappings indicating how the class interacts with its
|
|
* host element (host bindings, listeners, etc).
|
|
*/
|
|
export interface R3HostMetadata {
|
|
/**
|
|
* A mapping of attribute binding keys to `o.Expression`s.
|
|
*/
|
|
attributes: {[key: string]: o.Expression};
|
|
|
|
/**
|
|
* A mapping of event binding keys to unparsed expressions.
|
|
*/
|
|
listeners: {[key: string]: string};
|
|
|
|
/**
|
|
* A mapping of property binding keys to unparsed expressions.
|
|
*/
|
|
properties: {[key: string]: string};
|
|
|
|
specialAttributes: {styleAttr?: string; classAttr?: string;};
|
|
}
|