forked from angular/angular
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutil.ts
More file actions
178 lines (159 loc) Β· 5.81 KB
/
util.ts
File metadata and controls
178 lines (159 loc) Β· 5.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/**
* @license
* Copyright Google LLC 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.dev/license
*/
import {escapeIdentifier} from '../output/abstract_emitter';
import * as o from '../output/output_ast';
import {Identifiers} from './r3_identifiers';
export function typeWithParameters(type: o.Expression, numParams: number): o.ExpressionType {
if (numParams === 0) {
return o.expressionType(type);
}
const params: o.Type[] = [];
for (let i = 0; i < numParams; i++) {
params.push(o.DYNAMIC_TYPE);
}
return o.expressionType(type, undefined, params);
}
export interface R3Reference {
value: o.Expression;
type: o.Expression;
}
/**
* Result of compilation of a render3 code unit, e.g. component, directive, pipe, etc.
*/
export interface R3CompiledExpression {
expression: o.Expression;
type: o.Type;
statements: o.Statement[];
}
const ANIMATE_SYMBOL_PREFIX = '@';
export function prepareSyntheticPropertyName(name: string) {
return `${ANIMATE_SYMBOL_PREFIX}${name}`;
}
export function prepareSyntheticListenerName(name: string, phase: string) {
return `${ANIMATE_SYMBOL_PREFIX}${name}.${phase}`;
}
export function getSafePropertyAccessString(accessor: string, name: string): string {
const escapedName = escapeIdentifier(name, false, false);
return escapedName !== name ? `${accessor}[${escapedName}]` : `${accessor}.${name}`;
}
export function prepareSyntheticListenerFunctionName(name: string, phase: string) {
return `animation_${name}_${phase}`;
}
export function jitOnlyGuardedExpression(expr: o.Expression): o.Expression {
return guardedExpression('ngJitMode', expr);
}
export function devOnlyGuardedExpression(expr: o.Expression): o.Expression {
return guardedExpression('ngDevMode', expr);
}
export function guardedExpression(guard: string, expr: o.Expression): o.Expression {
const guardExpr = new o.ExternalExpr({name: guard, moduleName: null});
const guardNotDefined = new o.BinaryOperatorExpr(
o.BinaryOperator.Identical,
new o.TypeofExpr(guardExpr),
o.literal('undefined'),
);
const guardUndefinedOrTrue = new o.BinaryOperatorExpr(
o.BinaryOperator.Or,
guardNotDefined,
guardExpr,
/* type */ undefined,
/* sourceSpan */ undefined,
true,
);
return new o.BinaryOperatorExpr(o.BinaryOperator.And, guardUndefinedOrTrue, expr);
}
export function wrapReference(value: any): R3Reference {
const wrapped = new o.WrappedNodeExpr(value);
return {value: wrapped, type: wrapped};
}
export function refsToArray(refs: R3Reference[], shouldForwardDeclare: boolean): o.Expression {
const values = o.literalArr(refs.map((ref) => ref.value));
return shouldForwardDeclare ? o.arrowFn([], values) : values;
}
/**
* Describes an expression that may have been wrapped in a `forwardRef()` guard.
*
* This is used when describing expressions that can refer to types that may eagerly reference types
* that have not yet been defined.
*/
export interface MaybeForwardRefExpression<T extends o.Expression = o.Expression> {
/**
* The unwrapped expression.
*/
expression: T;
/**
* Specified whether the `expression` contains a reference to something that has not yet been
* defined, and whether the expression is still wrapped in a `forwardRef()` call.
*
* If this value is `ForwardRefHandling.None` then the `expression` is safe to use as-is.
*
* Otherwise the `expression` was wrapped in a call to `forwardRef()` and must not be eagerly
* evaluated. Instead it must be wrapped in a function closure that will be evaluated lazily to
* allow the definition of the expression to be evaluated first.
*
* In full AOT compilation it can be safe to unwrap the `forwardRef()` call up front if the
* expression will actually be evaluated lazily inside a function call after the value of
* `expression` has been defined.
*
* But in other cases, such as partial AOT compilation or JIT compilation the expression will be
* evaluated eagerly in top level code so will need to continue to be wrapped in a `forwardRef()`
* call.
*
*/
forwardRef: ForwardRefHandling;
}
export function createMayBeForwardRefExpression<T extends o.Expression>(
expression: T,
forwardRef: ForwardRefHandling,
): MaybeForwardRefExpression<T> {
return {expression, forwardRef};
}
/**
* Convert a `MaybeForwardRefExpression` to an `Expression`, possibly wrapping its expression in a
* `forwardRef()` call.
*
* If `MaybeForwardRefExpression.forwardRef` is `ForwardRefHandling.Unwrapped` then the expression
* was originally wrapped in a `forwardRef()` call to prevent the value from being eagerly evaluated
* in the code.
*
* See `packages/compiler-cli/src/ngtsc/annotations/src/injectable.ts` and
* `packages/compiler/src/jit_compiler_facade.ts` for more information.
*/
export function convertFromMaybeForwardRefExpression({
expression,
forwardRef,
}: MaybeForwardRefExpression): o.Expression {
switch (forwardRef) {
case ForwardRefHandling.None:
case ForwardRefHandling.Wrapped:
return expression;
case ForwardRefHandling.Unwrapped:
return generateForwardRef(expression);
}
}
/**
* Generate an expression that has the given `expr` wrapped in the following form:
*
* ```
* forwardRef(() => expr)
* ```
*/
export function generateForwardRef(expr: o.Expression): o.Expression {
return o.importExpr(Identifiers.forwardRef).callFn([o.arrowFn([], expr)]);
}
/**
* Specifies how a forward ref has been handled in a MaybeForwardRefExpression
*/
export const enum ForwardRefHandling {
/** The expression was not wrapped in a `forwardRef()` call in the first place. */
None,
/** The expression is still wrapped in a `forwardRef()` call. */
Wrapped,
/** The expression was wrapped in a `forwardRef()` call but has since been unwrapped. */
Unwrapped,
}