1 | /**
|
---|
2 | * @license
|
---|
3 | * Copyright Google LLC All Rights Reserved.
|
---|
4 | *
|
---|
5 | * Use of this source code is governed by an MIT-style license that can be
|
---|
6 | * found in the LICENSE file at https://angular.io/license
|
---|
7 | */
|
---|
8 | /// <amd-module name="@angular/compiler-cli/ngcc/src/host/esm5_host" />
|
---|
9 | import * as ts from 'typescript';
|
---|
10 | import { ClassDeclaration, ClassMember, Declaration, Decorator, FunctionDefinition } from '../../../src/ngtsc/reflection';
|
---|
11 | import { Esm2015ReflectionHost, ParamInfo } from './esm2015_host';
|
---|
12 | import { NgccClassSymbol } from './ngcc_host';
|
---|
13 | /**
|
---|
14 | * ESM5 packages contain ECMAScript IIFE functions that act like classes. For example:
|
---|
15 | *
|
---|
16 | * ```
|
---|
17 | * var CommonModule = (function () {
|
---|
18 | * function CommonModule() {
|
---|
19 | * }
|
---|
20 | * CommonModule.decorators = [ ... ];
|
---|
21 | * return CommonModule;
|
---|
22 | * ```
|
---|
23 | *
|
---|
24 | * * "Classes" are decorated if they have a static property called `decorators`.
|
---|
25 | * * Members are decorated if there is a matching key on a static property
|
---|
26 | * called `propDecorators`.
|
---|
27 | * * Constructor parameters decorators are found on an object returned from
|
---|
28 | * a static method called `ctorParameters`.
|
---|
29 | *
|
---|
30 | */
|
---|
31 | export declare class Esm5ReflectionHost extends Esm2015ReflectionHost {
|
---|
32 | getBaseClassExpression(clazz: ClassDeclaration): ts.Expression | null;
|
---|
33 | /**
|
---|
34 | * Trace an identifier to its declaration, if possible.
|
---|
35 | *
|
---|
36 | * This method attempts to resolve the declaration of the given identifier, tracing back through
|
---|
37 | * imports and re-exports until the original declaration statement is found. A `Declaration`
|
---|
38 | * object is returned if the original declaration is found, or `null` is returned otherwise.
|
---|
39 | *
|
---|
40 | * In ES5, the implementation of a class is a function expression that is hidden inside an IIFE.
|
---|
41 | * If we are looking for the declaration of the identifier of the inner function expression, we
|
---|
42 | * will get hold of the outer "class" variable declaration and return its identifier instead. See
|
---|
43 | * `getClassDeclarationFromInnerFunctionDeclaration()` for more info.
|
---|
44 | *
|
---|
45 | * @param id a TypeScript `ts.Identifier` to trace back to a declaration.
|
---|
46 | *
|
---|
47 | * @returns metadata about the `Declaration` if the original declaration is found, or `null`
|
---|
48 | * otherwise.
|
---|
49 | */
|
---|
50 | getDeclarationOfIdentifier(id: ts.Identifier): Declaration | null;
|
---|
51 | /**
|
---|
52 | * Parse a function declaration to find the relevant metadata about it.
|
---|
53 | *
|
---|
54 | * In ESM5 we need to do special work with optional arguments to the function, since they get
|
---|
55 | * their own initializer statement that needs to be parsed and then not included in the "body"
|
---|
56 | * statements of the function.
|
---|
57 | *
|
---|
58 | * @param node the function declaration to parse.
|
---|
59 | * @returns an object containing the node, statements and parameters of the function.
|
---|
60 | */
|
---|
61 | getDefinitionOfFunction(node: ts.Node): FunctionDefinition | null;
|
---|
62 | /**
|
---|
63 | * Check whether a `Declaration` corresponds with a known declaration, such as a TypeScript helper
|
---|
64 | * function, and set its `known` property to the appropriate `KnownDeclaration`.
|
---|
65 | *
|
---|
66 | * @param decl The `Declaration` to check.
|
---|
67 | * @return The passed in `Declaration` (potentially enhanced with a `KnownDeclaration`).
|
---|
68 | */
|
---|
69 | detectKnownDeclaration<T extends Declaration>(decl: T): T;
|
---|
70 | /**
|
---|
71 | * In ES5, the implementation of a class is a function expression that is hidden inside an IIFE,
|
---|
72 | * whose value is assigned to a variable (which represents the class to the rest of the program).
|
---|
73 | * So we might need to dig around to get hold of the "class" declaration.
|
---|
74 | *
|
---|
75 | * This method extracts a `NgccClassSymbol` if `declaration` is the function declaration inside
|
---|
76 | * the IIFE. Otherwise, undefined is returned.
|
---|
77 | *
|
---|
78 | * @param declaration the declaration whose symbol we are finding.
|
---|
79 | * @returns the symbol for the node or `undefined` if it is not a "class" or has no symbol.
|
---|
80 | */
|
---|
81 | protected getClassSymbolFromInnerDeclaration(declaration: ts.Node): NgccClassSymbol | undefined;
|
---|
82 | /**
|
---|
83 | * Find the declarations of the constructor parameters of a class identified by its symbol.
|
---|
84 | *
|
---|
85 | * In ESM5, there is no "class" so the constructor that we want is actually the inner function
|
---|
86 | * declaration inside the IIFE, whose return value is assigned to the outer variable declaration
|
---|
87 | * (that represents the class to the rest of the program).
|
---|
88 | *
|
---|
89 | * @param classSymbol the symbol of the class (i.e. the outer variable declaration) whose
|
---|
90 | * parameters we want to find.
|
---|
91 | * @returns an array of `ts.ParameterDeclaration` objects representing each of the parameters in
|
---|
92 | * the class's constructor or `null` if there is no constructor.
|
---|
93 | */
|
---|
94 | protected getConstructorParameterDeclarations(classSymbol: NgccClassSymbol): ts.ParameterDeclaration[] | null;
|
---|
95 | /**
|
---|
96 | * Get the parameter type and decorators for the constructor of a class,
|
---|
97 | * where the information is stored on a static method of the class.
|
---|
98 | *
|
---|
99 | * In this case the decorators are stored in the body of a method
|
---|
100 | * (`ctorParatemers`) attached to the constructor function.
|
---|
101 | *
|
---|
102 | * Note that unlike ESM2015 this is a function expression rather than an arrow
|
---|
103 | * function:
|
---|
104 | *
|
---|
105 | * ```
|
---|
106 | * SomeDirective.ctorParameters = function() { return [
|
---|
107 | * { type: ViewContainerRef, },
|
---|
108 | * { type: TemplateRef, },
|
---|
109 | * { type: IterableDiffers, },
|
---|
110 | * { type: undefined, decorators: [{ type: Inject, args: [INJECTED_TOKEN,] },] },
|
---|
111 | * ]; };
|
---|
112 | * ```
|
---|
113 | *
|
---|
114 | * @param paramDecoratorsProperty the property that holds the parameter info we want to get.
|
---|
115 | * @returns an array of objects containing the type and decorators for each parameter.
|
---|
116 | */
|
---|
117 | protected getParamInfoFromStaticProperty(paramDecoratorsProperty: ts.Symbol): ParamInfo[] | null;
|
---|
118 | /**
|
---|
119 | * Reflect over a symbol and extract the member information, combining it with the
|
---|
120 | * provided decorator information, and whether it is a static member.
|
---|
121 | *
|
---|
122 | * If a class member uses accessors (e.g getters and/or setters) then it gets downleveled
|
---|
123 | * in ES5 to a single `Object.defineProperty()` call. In that case we must parse this
|
---|
124 | * call to extract the one or two ClassMember objects that represent the accessors.
|
---|
125 | *
|
---|
126 | * @param symbol the symbol for the member to reflect over.
|
---|
127 | * @param decorators an array of decorators associated with the member.
|
---|
128 | * @param isStatic true if this member is static, false if it is an instance property.
|
---|
129 | * @returns the reflected member information, or null if the symbol is not a member.
|
---|
130 | */
|
---|
131 | protected reflectMembers(symbol: ts.Symbol, decorators?: Decorator[], isStatic?: boolean): ClassMember[] | null;
|
---|
132 | /**
|
---|
133 | * Find statements related to the given class that may contain calls to a helper.
|
---|
134 | *
|
---|
135 | * In ESM5 code the helper calls are hidden inside the class's IIFE.
|
---|
136 | *
|
---|
137 | * @param classSymbol the class whose helper calls we are interested in. We expect this symbol
|
---|
138 | * to reference the inner identifier inside the IIFE.
|
---|
139 | * @returns an array of statements that may contain helper calls.
|
---|
140 | */
|
---|
141 | protected getStatementsForClass(classSymbol: NgccClassSymbol): ts.Statement[];
|
---|
142 | /**
|
---|
143 | * A constructor function may have been "synthesized" by TypeScript during JavaScript emit,
|
---|
144 | * in the case no user-defined constructor exists and e.g. property initializers are used.
|
---|
145 | * Those initializers need to be emitted into a constructor in JavaScript, so the TypeScript
|
---|
146 | * compiler generates a synthetic constructor.
|
---|
147 | *
|
---|
148 | * We need to identify such constructors as ngcc needs to be able to tell if a class did
|
---|
149 | * originally have a constructor in the TypeScript source. For ES5, we can not tell an
|
---|
150 | * empty constructor apart from a synthesized constructor, but fortunately that does not
|
---|
151 | * matter for the code generated by ngtsc.
|
---|
152 | *
|
---|
153 | * When a class has a superclass however, a synthesized constructor must not be considered
|
---|
154 | * as a user-defined constructor as that prevents a base factory call from being created by
|
---|
155 | * ngtsc, resulting in a factory function that does not inject the dependencies of the
|
---|
156 | * superclass. Hence, we identify a default synthesized super call in the constructor body,
|
---|
157 | * according to the structure that TypeScript's ES2015 to ES5 transformer generates in
|
---|
158 | * https://github.com/Microsoft/TypeScript/blob/v3.2.2/src/compiler/transformers/es2015.ts#L1082-L1098
|
---|
159 | *
|
---|
160 | * Additionally, we handle synthetic delegate constructors that are emitted when TypeScript
|
---|
161 | * downlevel's ES2015 synthetically generated to ES5. These vary slightly from the default
|
---|
162 | * structure mentioned above because the ES2015 output uses a spread operator, for delegating
|
---|
163 | * to the parent constructor, that is preserved through a TypeScript helper in ES5. e.g.
|
---|
164 | *
|
---|
165 | * ```
|
---|
166 | * return _super.apply(this, tslib.__spread(arguments)) || this;
|
---|
167 | * ```
|
---|
168 | *
|
---|
169 | * or, since TypeScript 4.2 it would be
|
---|
170 | *
|
---|
171 | * ```
|
---|
172 | * return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this;
|
---|
173 | * ```
|
---|
174 | *
|
---|
175 | * Such constructs can be still considered as synthetic delegate constructors as they are
|
---|
176 | * the product of a common TypeScript to ES5 synthetic constructor, just being downleveled
|
---|
177 | * to ES5 using `tsc`. See: https://github.com/angular/angular/issues/38453.
|
---|
178 | *
|
---|
179 | *
|
---|
180 | * @param constructor a constructor function to test
|
---|
181 | * @returns true if the constructor appears to have been synthesized
|
---|
182 | */
|
---|
183 | private isSynthesizedConstructor;
|
---|
184 | /**
|
---|
185 | * Identifies synthesized super calls which pass-through function arguments directly and are
|
---|
186 | * being assigned to a common `_this` variable. The following patterns we intend to match:
|
---|
187 | *
|
---|
188 | * 1. Delegate call emitted by TypeScript when it emits ES5 directly.
|
---|
189 | * ```
|
---|
190 | * var _this = _super !== null && _super.apply(this, arguments) || this;
|
---|
191 | * ```
|
---|
192 | *
|
---|
193 | * 2. Delegate call emitted by TypeScript when it downlevel's ES2015 to ES5.
|
---|
194 | * ```
|
---|
195 | * var _this = _super.apply(this, tslib.__spread(arguments)) || this;
|
---|
196 | * ```
|
---|
197 | * or using the syntax emitted since TypeScript 4.2:
|
---|
198 | * ```
|
---|
199 | * return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this;
|
---|
200 | * ```
|
---|
201 | *
|
---|
202 | * @param statement a statement that may be a synthesized super call
|
---|
203 | * @returns true if the statement looks like a synthesized super call
|
---|
204 | */
|
---|
205 | private isSynthesizedSuperThisAssignment;
|
---|
206 | /**
|
---|
207 | * Identifies synthesized super calls which pass-through function arguments directly and
|
---|
208 | * are being returned. The following patterns correspond to synthetic super return calls:
|
---|
209 | *
|
---|
210 | * 1. Delegate call emitted by TypeScript when it emits ES5 directly.
|
---|
211 | * ```
|
---|
212 | * return _super !== null && _super.apply(this, arguments) || this;
|
---|
213 | * ```
|
---|
214 | *
|
---|
215 | * 2. Delegate call emitted by TypeScript when it downlevel's ES2015 to ES5.
|
---|
216 | * ```
|
---|
217 | * return _super.apply(this, tslib.__spread(arguments)) || this;
|
---|
218 | * ```
|
---|
219 | * or using the syntax emitted since TypeScript 4.2:
|
---|
220 | * ```
|
---|
221 | * return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this;
|
---|
222 | * ```
|
---|
223 | *
|
---|
224 | * @param statement a statement that may be a synthesized super call
|
---|
225 | * @returns true if the statement looks like a synthesized super call
|
---|
226 | */
|
---|
227 | private isSynthesizedSuperReturnStatement;
|
---|
228 | /**
|
---|
229 | * Identifies synthesized super calls which pass-through function arguments directly. The
|
---|
230 | * synthetic delegate super call match the following patterns we intend to match:
|
---|
231 | *
|
---|
232 | * 1. Delegate call emitted by TypeScript when it emits ES5 directly.
|
---|
233 | * ```
|
---|
234 | * _super !== null && _super.apply(this, arguments) || this;
|
---|
235 | * ```
|
---|
236 | *
|
---|
237 | * 2. Delegate call emitted by TypeScript when it downlevel's ES2015 to ES5.
|
---|
238 | * ```
|
---|
239 | * _super.apply(this, tslib.__spread(arguments)) || this;
|
---|
240 | * ```
|
---|
241 | * or using the syntax emitted since TypeScript 4.2:
|
---|
242 | * ```
|
---|
243 | * return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this;
|
---|
244 | * ```
|
---|
245 | *
|
---|
246 | * @param expression an expression that may represent a default super call
|
---|
247 | * @returns true if the expression corresponds with the above form
|
---|
248 | */
|
---|
249 | private isSynthesizedDefaultSuperCall;
|
---|
250 | /**
|
---|
251 | * Tests whether the expression corresponds to a `super` call passing through
|
---|
252 | * function arguments without any modification. e.g.
|
---|
253 | *
|
---|
254 | * ```
|
---|
255 | * _super !== null && _super.apply(this, arguments) || this;
|
---|
256 | * ```
|
---|
257 | *
|
---|
258 | * This structure is generated by TypeScript when transforming ES2015 to ES5, see
|
---|
259 | * https://github.com/Microsoft/TypeScript/blob/v3.2.2/src/compiler/transformers/es2015.ts#L1148-L1163
|
---|
260 | *
|
---|
261 | * Additionally, we also handle cases where `arguments` are wrapped by a TypeScript spread
|
---|
262 | * helper.
|
---|
263 | * This can happen if ES2015 class output contain auto-generated constructors due to class
|
---|
264 | * members. The ES2015 output will be using `super(...arguments)` to delegate to the superclass,
|
---|
265 | * but once downleveled to ES5, the spread operator will be persisted through a TypeScript spread
|
---|
266 | * helper. For example:
|
---|
267 | *
|
---|
268 | * ```
|
---|
269 | * _super.apply(this, __spread(arguments)) || this;
|
---|
270 | * ```
|
---|
271 | *
|
---|
272 | * or, since TypeScript 4.2 it would be
|
---|
273 | *
|
---|
274 | * ```
|
---|
275 | * _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this;
|
---|
276 | * ```
|
---|
277 | *
|
---|
278 | * More details can be found in: https://github.com/angular/angular/issues/38453.
|
---|
279 | *
|
---|
280 | * @param expression an expression that may represent a default super call
|
---|
281 | * @returns true if the expression corresponds with the above form
|
---|
282 | */
|
---|
283 | private isSuperApplyCall;
|
---|
284 | /**
|
---|
285 | * Determines if the provided expression is one of the following call expressions:
|
---|
286 | *
|
---|
287 | * 1. `__spread(arguments)`
|
---|
288 | * 2. `__spreadArray([], __read(arguments))`
|
---|
289 | *
|
---|
290 | * The tslib helpers may have been emitted inline as in the above example, or they may be read
|
---|
291 | * from a namespace import.
|
---|
292 | */
|
---|
293 | private isSpreadArgumentsExpression;
|
---|
294 | /**
|
---|
295 | * Inspects the provided expression and determines if it corresponds with a known helper function
|
---|
296 | * as receiver expression.
|
---|
297 | */
|
---|
298 | private extractKnownHelperCall;
|
---|
299 | }
|
---|