@angular/core 20.1.0-rc.0 → 20.2.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/api.d.d.ts +1 -1
  2. package/chrome_dev_tools_performance.d.d.ts +1 -1
  3. package/discovery.d.d.ts +1 -1
  4. package/event_dispatcher.d.d.ts +1 -1
  5. package/fesm2022/attribute.mjs +1 -1
  6. package/fesm2022/core.mjs +3 -3
  7. package/fesm2022/core.mjs.map +1 -1
  8. package/fesm2022/debug_node.mjs +7 -5
  9. package/fesm2022/debug_node.mjs.map +1 -1
  10. package/fesm2022/not_found.mjs +1 -1
  11. package/fesm2022/primitives/di.mjs +1 -1
  12. package/fesm2022/primitives/event-dispatch.mjs +1 -1
  13. package/fesm2022/primitives/signals.mjs +1 -1
  14. package/fesm2022/resource.mjs +1 -1
  15. package/fesm2022/root_effect_scheduler.mjs +1 -1
  16. package/fesm2022/rxjs-interop.mjs +1 -1
  17. package/fesm2022/signal.mjs +1 -1
  18. package/fesm2022/testing.mjs +1 -1
  19. package/fesm2022/untracked.mjs +1 -1
  20. package/fesm2022/weak_ref.mjs +1 -1
  21. package/graph.d.d.ts +1 -1
  22. package/index.d.ts +2 -2
  23. package/package.json +2 -2
  24. package/primitives/di/index.d.ts +1 -1
  25. package/primitives/event-dispatch/index.d.ts +1 -1
  26. package/primitives/signals/index.d.ts +1 -1
  27. package/rxjs-interop/index.d.ts +1 -1
  28. package/schematics/bundles/{apply_import_manager-DEMoyu96.cjs → apply_import_manager-B0fYYMpr.cjs} +3 -3
  29. package/schematics/bundles/{checker-CwuJOWZI.cjs → checker-DLInMAS3.cjs} +382 -1109
  30. package/schematics/bundles/cleanup-unused-imports.cjs +6 -5
  31. package/schematics/bundles/{compiler_host-B1N_OYoF.cjs → compiler_host-Doj9KVJf.cjs} +2 -2
  32. package/schematics/bundles/control-flow-migration.cjs +3 -3
  33. package/schematics/bundles/document-core.cjs +6 -5
  34. package/schematics/bundles/imports-CIX-JgAN.cjs +1 -1
  35. package/schematics/bundles/{index-CmuNlSML.cjs → index-BmuUS1AB.cjs} +930 -54
  36. package/schematics/bundles/{index-DPxKO2pR.cjs → index-Bp8sCiq1.cjs} +5 -4
  37. package/schematics/bundles/inject-flags.cjs +6 -5
  38. package/schematics/bundles/inject-migration.cjs +3 -3
  39. package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
  40. package/schematics/bundles/{migrate_ts_type_references-Da3yLjVM.cjs → migrate_ts_type_references-CmZ0155c.cjs} +6 -5
  41. package/schematics/bundles/ng_decorators-B5HCqr20.cjs +1 -1
  42. package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
  43. package/schematics/bundles/output-migration.cjs +7 -6
  44. package/schematics/bundles/{project_paths-86Qe1BQQ.cjs → project_paths-D2SJWT7x.cjs} +39 -3
  45. package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +1 -1
  46. package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
  47. package/schematics/bundles/route-lazy-loading.cjs +3 -3
  48. package/schematics/bundles/self-closing-tags-migration.cjs +5 -4
  49. package/schematics/bundles/signal-input-migration.cjs +8 -7
  50. package/schematics/bundles/signal-queries-migration.cjs +8 -7
  51. package/schematics/bundles/signals.cjs +8 -7
  52. package/schematics/bundles/standalone-migration.cjs +4 -4
  53. package/schematics/bundles/symbol-VPWguRxr.cjs +1 -1
  54. package/schematics/bundles/test-bed-get.cjs +5 -4
  55. package/signal.d.d.ts +1 -1
  56. package/testing/index.d.ts +1 -1
  57. package/weak_ref.d.d.ts +1 -1
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v20.1.0-rc.0
3
+ * @license Angular v20.2.0-next.0
4
4
  * (c) 2010-2025 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
7
7
  'use strict';
8
8
 
9
- var checker = require('./checker-CwuJOWZI.cjs');
9
+ var checker = require('./checker-DLInMAS3.cjs');
10
10
  var ts = require('typescript');
11
11
  var p = require('path');
12
12
  require('os');
@@ -891,7 +891,7 @@ const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
891
891
  function compileDeclareClassMetadata(metadata) {
892
892
  const definitionMap = new checker.DefinitionMap();
893
893
  definitionMap.set('minVersion', checker.literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
894
- definitionMap.set('version', checker.literal('20.1.0-rc.0'));
894
+ definitionMap.set('version', checker.literal('20.2.0-next.0'));
895
895
  definitionMap.set('ngImport', checker.importExpr(checker.Identifiers.core));
896
896
  definitionMap.set('type', metadata.type);
897
897
  definitionMap.set('decorators', metadata.decorators);
@@ -909,7 +909,7 @@ function compileComponentDeclareClassMetadata(metadata, dependencies) {
909
909
  callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? checker.literal(null));
910
910
  callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? checker.literal(null));
911
911
  definitionMap.set('minVersion', checker.literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
912
- definitionMap.set('version', checker.literal('20.1.0-rc.0'));
912
+ definitionMap.set('version', checker.literal('20.2.0-next.0'));
913
913
  definitionMap.set('ngImport', checker.importExpr(checker.Identifiers.core));
914
914
  definitionMap.set('type', metadata.type);
915
915
  definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
@@ -1004,7 +1004,7 @@ function createDirectiveDefinitionMap(meta) {
1004
1004
  const definitionMap = new checker.DefinitionMap();
1005
1005
  const minVersion = getMinimumVersionForPartialOutput(meta);
1006
1006
  definitionMap.set('minVersion', checker.literal(minVersion));
1007
- definitionMap.set('version', checker.literal('20.1.0-rc.0'));
1007
+ definitionMap.set('version', checker.literal('20.2.0-next.0'));
1008
1008
  // e.g. `type: MyDirective`
1009
1009
  definitionMap.set('type', meta.type.value);
1010
1010
  if (meta.isStandalone !== undefined) {
@@ -1420,7 +1420,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
1420
1420
  function compileDeclareFactoryFunction(meta) {
1421
1421
  const definitionMap = new checker.DefinitionMap();
1422
1422
  definitionMap.set('minVersion', checker.literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
1423
- definitionMap.set('version', checker.literal('20.1.0-rc.0'));
1423
+ definitionMap.set('version', checker.literal('20.2.0-next.0'));
1424
1424
  definitionMap.set('ngImport', checker.importExpr(checker.Identifiers.core));
1425
1425
  definitionMap.set('type', meta.type.value);
1426
1426
  definitionMap.set('deps', compileDependencies(meta.deps));
@@ -1455,7 +1455,7 @@ function compileDeclareInjectableFromMetadata(meta) {
1455
1455
  function createInjectableDefinitionMap(meta) {
1456
1456
  const definitionMap = new checker.DefinitionMap();
1457
1457
  definitionMap.set('minVersion', checker.literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
1458
- definitionMap.set('version', checker.literal('20.1.0-rc.0'));
1458
+ definitionMap.set('version', checker.literal('20.2.0-next.0'));
1459
1459
  definitionMap.set('ngImport', checker.importExpr(checker.Identifiers.core));
1460
1460
  definitionMap.set('type', meta.type.value);
1461
1461
  // Only generate providedIn property if it has a non-null value
@@ -1506,7 +1506,7 @@ function compileDeclareInjectorFromMetadata(meta) {
1506
1506
  function createInjectorDefinitionMap(meta) {
1507
1507
  const definitionMap = new checker.DefinitionMap();
1508
1508
  definitionMap.set('minVersion', checker.literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
1509
- definitionMap.set('version', checker.literal('20.1.0-rc.0'));
1509
+ definitionMap.set('version', checker.literal('20.2.0-next.0'));
1510
1510
  definitionMap.set('ngImport', checker.importExpr(checker.Identifiers.core));
1511
1511
  definitionMap.set('type', meta.type.value);
1512
1512
  definitionMap.set('providers', meta.providers);
@@ -1539,7 +1539,7 @@ function createNgModuleDefinitionMap(meta) {
1539
1539
  throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
1540
1540
  }
1541
1541
  definitionMap.set('minVersion', checker.literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
1542
- definitionMap.set('version', checker.literal('20.1.0-rc.0'));
1542
+ definitionMap.set('version', checker.literal('20.2.0-next.0'));
1543
1543
  definitionMap.set('ngImport', checker.importExpr(checker.Identifiers.core));
1544
1544
  definitionMap.set('type', meta.type.value);
1545
1545
  // We only generate the keys in the metadata if the arrays contain values.
@@ -1590,7 +1590,7 @@ function compileDeclarePipeFromMetadata(meta) {
1590
1590
  function createPipeDefinitionMap(meta) {
1591
1591
  const definitionMap = new checker.DefinitionMap();
1592
1592
  definitionMap.set('minVersion', checker.literal(MINIMUM_PARTIAL_LINKER_VERSION));
1593
- definitionMap.set('version', checker.literal('20.1.0-rc.0'));
1593
+ definitionMap.set('version', checker.literal('20.2.0-next.0'));
1594
1594
  definitionMap.set('ngImport', checker.importExpr(checker.Identifiers.core));
1595
1595
  // e.g. `type: MyPipe`
1596
1596
  definitionMap.set('type', meta.type.value);
@@ -2996,6 +2996,790 @@ function resolveOutput(bindingName) {
2996
2996
  return bindingName;
2997
2997
  }
2998
2998
 
2999
+ class ArraySliceBuiltinFn extends checker.KnownFn {
3000
+ lhs;
3001
+ constructor(lhs) {
3002
+ super();
3003
+ this.lhs = lhs;
3004
+ }
3005
+ evaluate(node, args) {
3006
+ if (args.length === 0) {
3007
+ return this.lhs;
3008
+ }
3009
+ else {
3010
+ return checker.DynamicValue.fromUnknown(node);
3011
+ }
3012
+ }
3013
+ }
3014
+ class ArrayConcatBuiltinFn extends checker.KnownFn {
3015
+ lhs;
3016
+ constructor(lhs) {
3017
+ super();
3018
+ this.lhs = lhs;
3019
+ }
3020
+ evaluate(node, args) {
3021
+ const result = [...this.lhs];
3022
+ for (const arg of args) {
3023
+ if (arg instanceof checker.DynamicValue) {
3024
+ result.push(checker.DynamicValue.fromDynamicInput(node, arg));
3025
+ }
3026
+ else if (Array.isArray(arg)) {
3027
+ result.push(...arg);
3028
+ }
3029
+ else {
3030
+ result.push(arg);
3031
+ }
3032
+ }
3033
+ return result;
3034
+ }
3035
+ }
3036
+ class StringConcatBuiltinFn extends checker.KnownFn {
3037
+ lhs;
3038
+ constructor(lhs) {
3039
+ super();
3040
+ this.lhs = lhs;
3041
+ }
3042
+ evaluate(node, args) {
3043
+ let result = this.lhs;
3044
+ for (const arg of args) {
3045
+ const resolved = arg instanceof checker.EnumValue ? arg.resolved : arg;
3046
+ if (typeof resolved === 'string' ||
3047
+ typeof resolved === 'number' ||
3048
+ typeof resolved === 'boolean' ||
3049
+ resolved == null) {
3050
+ // Cast to `any`, because `concat` will convert
3051
+ // anything to a string, but TS only allows strings.
3052
+ result = result.concat(resolved);
3053
+ }
3054
+ else {
3055
+ return checker.DynamicValue.fromUnknown(node);
3056
+ }
3057
+ }
3058
+ return result;
3059
+ }
3060
+ }
3061
+
3062
+ /**
3063
+ * A value produced which originated in a `ForeignFunctionResolver` and doesn't come from the
3064
+ * template itself.
3065
+ *
3066
+ * Synthetic values cannot be further evaluated, and attempts to do so produce `DynamicValue`s
3067
+ * instead.
3068
+ */
3069
+ class SyntheticValue {
3070
+ value;
3071
+ constructor(value) {
3072
+ this.value = value;
3073
+ }
3074
+ }
3075
+
3076
+ function literalBinaryOp(op) {
3077
+ return { op, literal: true };
3078
+ }
3079
+ function referenceBinaryOp(op) {
3080
+ return { op, literal: false };
3081
+ }
3082
+ class StaticInterpreter {
3083
+ host;
3084
+ checker;
3085
+ dependencyTracker;
3086
+ BINARY_OPERATORS = new Map([
3087
+ [ts.SyntaxKind.PlusToken, literalBinaryOp((a, b) => a + b)],
3088
+ [ts.SyntaxKind.MinusToken, literalBinaryOp((a, b) => a - b)],
3089
+ [ts.SyntaxKind.AsteriskToken, literalBinaryOp((a, b) => a * b)],
3090
+ [ts.SyntaxKind.SlashToken, literalBinaryOp((a, b) => a / b)],
3091
+ [ts.SyntaxKind.PercentToken, literalBinaryOp((a, b) => a % b)],
3092
+ [ts.SyntaxKind.AmpersandToken, literalBinaryOp((a, b) => a & b)],
3093
+ [ts.SyntaxKind.BarToken, literalBinaryOp((a, b) => a | b)],
3094
+ [ts.SyntaxKind.CaretToken, literalBinaryOp((a, b) => a ^ b)],
3095
+ [ts.SyntaxKind.LessThanToken, literalBinaryOp((a, b) => a < b)],
3096
+ [ts.SyntaxKind.LessThanEqualsToken, literalBinaryOp((a, b) => a <= b)],
3097
+ [ts.SyntaxKind.GreaterThanToken, literalBinaryOp((a, b) => a > b)],
3098
+ [ts.SyntaxKind.GreaterThanEqualsToken, literalBinaryOp((a, b) => a >= b)],
3099
+ [ts.SyntaxKind.EqualsEqualsToken, literalBinaryOp((a, b) => a == b)],
3100
+ [ts.SyntaxKind.EqualsEqualsEqualsToken, literalBinaryOp((a, b) => a === b)],
3101
+ [ts.SyntaxKind.ExclamationEqualsToken, literalBinaryOp((a, b) => a != b)],
3102
+ [ts.SyntaxKind.ExclamationEqualsEqualsToken, literalBinaryOp((a, b) => a !== b)],
3103
+ [ts.SyntaxKind.LessThanLessThanToken, literalBinaryOp((a, b) => a << b)],
3104
+ [ts.SyntaxKind.GreaterThanGreaterThanToken, literalBinaryOp((a, b) => a >> b)],
3105
+ [ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken, literalBinaryOp((a, b) => a >>> b)],
3106
+ [ts.SyntaxKind.AsteriskAsteriskToken, literalBinaryOp((a, b) => Math.pow(a, b))],
3107
+ [ts.SyntaxKind.AmpersandAmpersandToken, referenceBinaryOp((a, b) => a && b)],
3108
+ [ts.SyntaxKind.BarBarToken, referenceBinaryOp((a, b) => a || b)],
3109
+ ]);
3110
+ UNARY_OPERATORS = new Map([
3111
+ [ts.SyntaxKind.TildeToken, (a) => ~a],
3112
+ [ts.SyntaxKind.MinusToken, (a) => -a],
3113
+ [ts.SyntaxKind.PlusToken, (a) => +a],
3114
+ [ts.SyntaxKind.ExclamationToken, (a) => !a],
3115
+ ]);
3116
+ constructor(host, checker, dependencyTracker) {
3117
+ this.host = host;
3118
+ this.checker = checker;
3119
+ this.dependencyTracker = dependencyTracker;
3120
+ }
3121
+ visit(node, context) {
3122
+ return this.visitExpression(node, context);
3123
+ }
3124
+ visitExpression(node, context) {
3125
+ let result;
3126
+ if (node.kind === ts.SyntaxKind.TrueKeyword) {
3127
+ return true;
3128
+ }
3129
+ else if (node.kind === ts.SyntaxKind.FalseKeyword) {
3130
+ return false;
3131
+ }
3132
+ else if (node.kind === ts.SyntaxKind.NullKeyword) {
3133
+ return null;
3134
+ }
3135
+ else if (ts.isStringLiteral(node)) {
3136
+ return node.text;
3137
+ }
3138
+ else if (ts.isNoSubstitutionTemplateLiteral(node)) {
3139
+ return node.text;
3140
+ }
3141
+ else if (ts.isTemplateExpression(node)) {
3142
+ result = this.visitTemplateExpression(node, context);
3143
+ }
3144
+ else if (ts.isNumericLiteral(node)) {
3145
+ return parseFloat(node.text);
3146
+ }
3147
+ else if (ts.isObjectLiteralExpression(node)) {
3148
+ result = this.visitObjectLiteralExpression(node, context);
3149
+ }
3150
+ else if (ts.isIdentifier(node)) {
3151
+ result = this.visitIdentifier(node, context);
3152
+ }
3153
+ else if (ts.isPropertyAccessExpression(node)) {
3154
+ result = this.visitPropertyAccessExpression(node, context);
3155
+ }
3156
+ else if (ts.isCallExpression(node)) {
3157
+ result = this.visitCallExpression(node, context);
3158
+ }
3159
+ else if (ts.isConditionalExpression(node)) {
3160
+ result = this.visitConditionalExpression(node, context);
3161
+ }
3162
+ else if (ts.isPrefixUnaryExpression(node)) {
3163
+ result = this.visitPrefixUnaryExpression(node, context);
3164
+ }
3165
+ else if (ts.isBinaryExpression(node)) {
3166
+ result = this.visitBinaryExpression(node, context);
3167
+ }
3168
+ else if (ts.isArrayLiteralExpression(node)) {
3169
+ result = this.visitArrayLiteralExpression(node, context);
3170
+ }
3171
+ else if (ts.isParenthesizedExpression(node)) {
3172
+ result = this.visitParenthesizedExpression(node, context);
3173
+ }
3174
+ else if (ts.isElementAccessExpression(node)) {
3175
+ result = this.visitElementAccessExpression(node, context);
3176
+ }
3177
+ else if (ts.isAsExpression(node)) {
3178
+ result = this.visitExpression(node.expression, context);
3179
+ }
3180
+ else if (ts.isNonNullExpression(node)) {
3181
+ result = this.visitExpression(node.expression, context);
3182
+ }
3183
+ else if (this.host.isClass(node)) {
3184
+ result = this.visitDeclaration(node, context);
3185
+ }
3186
+ else {
3187
+ return checker.DynamicValue.fromUnsupportedSyntax(node);
3188
+ }
3189
+ if (result instanceof checker.DynamicValue && result.node !== node) {
3190
+ return checker.DynamicValue.fromDynamicInput(node, result);
3191
+ }
3192
+ return result;
3193
+ }
3194
+ visitArrayLiteralExpression(node, context) {
3195
+ const array = [];
3196
+ for (let i = 0; i < node.elements.length; i++) {
3197
+ const element = node.elements[i];
3198
+ if (ts.isSpreadElement(element)) {
3199
+ array.push(...this.visitSpreadElement(element, context));
3200
+ }
3201
+ else {
3202
+ array.push(this.visitExpression(element, context));
3203
+ }
3204
+ }
3205
+ return array;
3206
+ }
3207
+ visitObjectLiteralExpression(node, context) {
3208
+ const map = new Map();
3209
+ for (let i = 0; i < node.properties.length; i++) {
3210
+ const property = node.properties[i];
3211
+ if (ts.isPropertyAssignment(property)) {
3212
+ const name = this.stringNameFromPropertyName(property.name, context);
3213
+ // Check whether the name can be determined statically.
3214
+ if (name === undefined) {
3215
+ return checker.DynamicValue.fromDynamicInput(node, checker.DynamicValue.fromDynamicString(property.name));
3216
+ }
3217
+ map.set(name, this.visitExpression(property.initializer, context));
3218
+ }
3219
+ else if (ts.isShorthandPropertyAssignment(property)) {
3220
+ const symbol = this.checker.getShorthandAssignmentValueSymbol(property);
3221
+ if (symbol === undefined || symbol.valueDeclaration === undefined) {
3222
+ map.set(property.name.text, checker.DynamicValue.fromUnknown(property));
3223
+ }
3224
+ else {
3225
+ map.set(property.name.text, this.visitDeclaration(symbol.valueDeclaration, context));
3226
+ }
3227
+ }
3228
+ else if (ts.isSpreadAssignment(property)) {
3229
+ const spread = this.visitExpression(property.expression, context);
3230
+ if (spread instanceof checker.DynamicValue) {
3231
+ return checker.DynamicValue.fromDynamicInput(node, spread);
3232
+ }
3233
+ else if (spread instanceof Map) {
3234
+ spread.forEach((value, key) => map.set(key, value));
3235
+ }
3236
+ else if (spread instanceof checker.ResolvedModule) {
3237
+ spread.getExports().forEach((value, key) => map.set(key, value));
3238
+ }
3239
+ else {
3240
+ return checker.DynamicValue.fromDynamicInput(node, checker.DynamicValue.fromInvalidExpressionType(property, spread));
3241
+ }
3242
+ }
3243
+ else {
3244
+ return checker.DynamicValue.fromUnknown(node);
3245
+ }
3246
+ }
3247
+ return map;
3248
+ }
3249
+ visitTemplateExpression(node, context) {
3250
+ const pieces = [node.head.text];
3251
+ for (let i = 0; i < node.templateSpans.length; i++) {
3252
+ const span = node.templateSpans[i];
3253
+ const value = literal(this.visit(span.expression, context), () => checker.DynamicValue.fromDynamicString(span.expression));
3254
+ if (value instanceof checker.DynamicValue) {
3255
+ return checker.DynamicValue.fromDynamicInput(node, value);
3256
+ }
3257
+ pieces.push(`${value}`, span.literal.text);
3258
+ }
3259
+ return pieces.join('');
3260
+ }
3261
+ visitIdentifier(node, context) {
3262
+ const decl = this.host.getDeclarationOfIdentifier(node);
3263
+ if (decl === null) {
3264
+ if (ts.identifierToKeywordKind(node) === ts.SyntaxKind.UndefinedKeyword) {
3265
+ return undefined;
3266
+ }
3267
+ else {
3268
+ // Check if the symbol here is imported.
3269
+ if (this.dependencyTracker !== null && this.host.getImportOfIdentifier(node) !== null) {
3270
+ // It was, but no declaration for the node could be found. This means that the dependency
3271
+ // graph for the current file cannot be properly updated to account for this (broken)
3272
+ // import. Instead, the originating file is reported as failing dependency analysis,
3273
+ // ensuring that future compilations will always attempt to re-resolve the previously
3274
+ // broken identifier.
3275
+ this.dependencyTracker.recordDependencyAnalysisFailure(context.originatingFile);
3276
+ }
3277
+ return checker.DynamicValue.fromUnknownIdentifier(node);
3278
+ }
3279
+ }
3280
+ const declContext = { ...context, ...joinModuleContext(context, node, decl) };
3281
+ const result = this.visitDeclaration(decl.node, declContext);
3282
+ if (result instanceof checker.Reference) {
3283
+ // Only record identifiers to non-synthetic references. Synthetic references may not have the
3284
+ // same value at runtime as they do at compile time, so it's not legal to refer to them by the
3285
+ // identifier here.
3286
+ if (!result.synthetic) {
3287
+ result.addIdentifier(node);
3288
+ }
3289
+ }
3290
+ else if (result instanceof checker.DynamicValue) {
3291
+ return checker.DynamicValue.fromDynamicInput(node, result);
3292
+ }
3293
+ return result;
3294
+ }
3295
+ visitDeclaration(node, context) {
3296
+ if (this.dependencyTracker !== null) {
3297
+ this.dependencyTracker.addDependency(context.originatingFile, node.getSourceFile());
3298
+ }
3299
+ if (this.host.isClass(node)) {
3300
+ return this.getReference(node, context);
3301
+ }
3302
+ else if (ts.isVariableDeclaration(node)) {
3303
+ return this.visitVariableDeclaration(node, context);
3304
+ }
3305
+ else if (ts.isParameter(node) && context.scope.has(node)) {
3306
+ return context.scope.get(node);
3307
+ }
3308
+ else if (ts.isExportAssignment(node)) {
3309
+ return this.visitExpression(node.expression, context);
3310
+ }
3311
+ else if (ts.isEnumDeclaration(node)) {
3312
+ return this.visitEnumDeclaration(node, context);
3313
+ }
3314
+ else if (ts.isSourceFile(node)) {
3315
+ return this.visitSourceFile(node, context);
3316
+ }
3317
+ else if (ts.isBindingElement(node)) {
3318
+ return this.visitBindingElement(node, context);
3319
+ }
3320
+ else {
3321
+ return this.getReference(node, context);
3322
+ }
3323
+ }
3324
+ visitVariableDeclaration(node, context) {
3325
+ const value = this.host.getVariableValue(node);
3326
+ if (value !== null) {
3327
+ return this.visitExpression(value, context);
3328
+ }
3329
+ else if (isVariableDeclarationDeclared(node)) {
3330
+ // If the declaration has a literal type that can be statically reduced to a value, resolve to
3331
+ // that value. If not, the historical behavior for variable declarations is to return a
3332
+ // `Reference` to the variable, as the consumer could use it in a context where knowing its
3333
+ // static value is not necessary.
3334
+ //
3335
+ // Arguably, since the value cannot be statically determined, we should return a
3336
+ // `DynamicValue`. This returns a `Reference` because it's the same behavior as before
3337
+ // `visitType` was introduced.
3338
+ //
3339
+ // TODO(zarend): investigate switching to a `DynamicValue` and verify this won't break any
3340
+ // use cases, especially in ngcc
3341
+ if (node.type !== undefined) {
3342
+ const evaluatedType = this.visitType(node.type, context);
3343
+ if (!(evaluatedType instanceof checker.DynamicValue)) {
3344
+ return evaluatedType;
3345
+ }
3346
+ }
3347
+ return this.getReference(node, context);
3348
+ }
3349
+ else {
3350
+ return undefined;
3351
+ }
3352
+ }
3353
+ visitEnumDeclaration(node, context) {
3354
+ const enumRef = this.getReference(node, context);
3355
+ const map = new Map();
3356
+ node.members.forEach((member, index) => {
3357
+ const name = this.stringNameFromPropertyName(member.name, context);
3358
+ if (name !== undefined) {
3359
+ const resolved = member.initializer ? this.visit(member.initializer, context) : index;
3360
+ map.set(name, new checker.EnumValue(enumRef, name, resolved));
3361
+ }
3362
+ });
3363
+ return map;
3364
+ }
3365
+ visitElementAccessExpression(node, context) {
3366
+ const lhs = this.visitExpression(node.expression, context);
3367
+ if (lhs instanceof checker.DynamicValue) {
3368
+ return checker.DynamicValue.fromDynamicInput(node, lhs);
3369
+ }
3370
+ const rhs = this.visitExpression(node.argumentExpression, context);
3371
+ if (rhs instanceof checker.DynamicValue) {
3372
+ return checker.DynamicValue.fromDynamicInput(node, rhs);
3373
+ }
3374
+ if (typeof rhs !== 'string' && typeof rhs !== 'number') {
3375
+ return checker.DynamicValue.fromInvalidExpressionType(node, rhs);
3376
+ }
3377
+ return this.accessHelper(node, lhs, rhs, context);
3378
+ }
3379
+ visitPropertyAccessExpression(node, context) {
3380
+ const lhs = this.visitExpression(node.expression, context);
3381
+ const rhs = node.name.text;
3382
+ // TODO: handle reference to class declaration.
3383
+ if (lhs instanceof checker.DynamicValue) {
3384
+ return checker.DynamicValue.fromDynamicInput(node, lhs);
3385
+ }
3386
+ return this.accessHelper(node, lhs, rhs, context);
3387
+ }
3388
+ visitSourceFile(node, context) {
3389
+ const declarations = this.host.getExportsOfModule(node);
3390
+ if (declarations === null) {
3391
+ return checker.DynamicValue.fromUnknown(node);
3392
+ }
3393
+ return new checker.ResolvedModule(declarations, (decl) => {
3394
+ const declContext = {
3395
+ ...context,
3396
+ ...joinModuleContext(context, node, decl),
3397
+ };
3398
+ // Visit both concrete and inline declarations.
3399
+ return this.visitDeclaration(decl.node, declContext);
3400
+ });
3401
+ }
3402
+ accessHelper(node, lhs, rhs, context) {
3403
+ const strIndex = `${rhs}`;
3404
+ if (lhs instanceof Map) {
3405
+ if (lhs.has(strIndex)) {
3406
+ return lhs.get(strIndex);
3407
+ }
3408
+ else {
3409
+ return undefined;
3410
+ }
3411
+ }
3412
+ else if (lhs instanceof checker.ResolvedModule) {
3413
+ return lhs.getExport(strIndex);
3414
+ }
3415
+ else if (Array.isArray(lhs)) {
3416
+ if (rhs === 'length') {
3417
+ return lhs.length;
3418
+ }
3419
+ else if (rhs === 'slice') {
3420
+ return new ArraySliceBuiltinFn(lhs);
3421
+ }
3422
+ else if (rhs === 'concat') {
3423
+ return new ArrayConcatBuiltinFn(lhs);
3424
+ }
3425
+ if (typeof rhs !== 'number' || !Number.isInteger(rhs)) {
3426
+ return checker.DynamicValue.fromInvalidExpressionType(node, rhs);
3427
+ }
3428
+ return lhs[rhs];
3429
+ }
3430
+ else if (typeof lhs === 'string' && rhs === 'concat') {
3431
+ return new StringConcatBuiltinFn(lhs);
3432
+ }
3433
+ else if (lhs instanceof checker.Reference) {
3434
+ const ref = lhs.node;
3435
+ if (this.host.isClass(ref)) {
3436
+ const module = owningModule(context, lhs.bestGuessOwningModule);
3437
+ let value = undefined;
3438
+ const member = this.host
3439
+ .getMembersOfClass(ref)
3440
+ .find((member) => member.isStatic && member.name === strIndex);
3441
+ if (member !== undefined) {
3442
+ if (member.value !== null) {
3443
+ value = this.visitExpression(member.value, context);
3444
+ }
3445
+ else if (member.implementation !== null) {
3446
+ value = new checker.Reference(member.implementation, module);
3447
+ }
3448
+ else if (member.node) {
3449
+ value = new checker.Reference(member.node, module);
3450
+ }
3451
+ }
3452
+ return value;
3453
+ }
3454
+ else if (checker.isDeclaration(ref)) {
3455
+ return checker.DynamicValue.fromDynamicInput(node, checker.DynamicValue.fromExternalReference(ref, lhs));
3456
+ }
3457
+ }
3458
+ else if (lhs instanceof checker.DynamicValue) {
3459
+ return checker.DynamicValue.fromDynamicInput(node, lhs);
3460
+ }
3461
+ else if (lhs instanceof SyntheticValue) {
3462
+ return checker.DynamicValue.fromSyntheticInput(node, lhs);
3463
+ }
3464
+ return checker.DynamicValue.fromUnknown(node);
3465
+ }
3466
+ visitCallExpression(node, context) {
3467
+ const lhs = this.visitExpression(node.expression, context);
3468
+ if (lhs instanceof checker.DynamicValue) {
3469
+ return checker.DynamicValue.fromDynamicInput(node, lhs);
3470
+ }
3471
+ // If the call refers to a builtin function, attempt to evaluate the function.
3472
+ if (lhs instanceof checker.KnownFn) {
3473
+ return lhs.evaluate(node, this.evaluateFunctionArguments(node, context));
3474
+ }
3475
+ if (!(lhs instanceof checker.Reference)) {
3476
+ return checker.DynamicValue.fromInvalidExpressionType(node.expression, lhs);
3477
+ }
3478
+ const fn = this.host.getDefinitionOfFunction(lhs.node);
3479
+ if (fn === null) {
3480
+ return checker.DynamicValue.fromInvalidExpressionType(node.expression, lhs);
3481
+ }
3482
+ if (!isFunctionOrMethodReference(lhs)) {
3483
+ return checker.DynamicValue.fromInvalidExpressionType(node.expression, lhs);
3484
+ }
3485
+ const resolveFfrExpr = (expr) => {
3486
+ let contextExtension = {};
3487
+ // TODO(alxhub): the condition `fn.body === null` here is vestigial - we probably _do_ want to
3488
+ // change the context like this even for non-null function bodies. But, this is being
3489
+ // redesigned as a refactoring with no behavior changes so that should be done as a follow-up.
3490
+ if (fn.body === null &&
3491
+ expr.getSourceFile() !== node.expression.getSourceFile() &&
3492
+ lhs.bestGuessOwningModule !== null) {
3493
+ contextExtension = {
3494
+ absoluteModuleName: lhs.bestGuessOwningModule.specifier,
3495
+ resolutionContext: lhs.bestGuessOwningModule.resolutionContext,
3496
+ };
3497
+ }
3498
+ return this.visitFfrExpression(expr, { ...context, ...contextExtension });
3499
+ };
3500
+ // If the function is foreign (declared through a d.ts file), attempt to resolve it with the
3501
+ // foreignFunctionResolver, if one is specified.
3502
+ if (fn.body === null && context.foreignFunctionResolver !== undefined) {
3503
+ const unresolvable = checker.DynamicValue.fromDynamicInput(node, checker.DynamicValue.fromExternalReference(node.expression, lhs));
3504
+ return context.foreignFunctionResolver(lhs, node, resolveFfrExpr, unresolvable);
3505
+ }
3506
+ const res = this.visitFunctionBody(node, fn, context);
3507
+ // If the result of attempting to resolve the function body was a DynamicValue, attempt to use
3508
+ // the foreignFunctionResolver if one is present. This could still potentially yield a usable
3509
+ // value.
3510
+ if (res instanceof checker.DynamicValue && context.foreignFunctionResolver !== undefined) {
3511
+ const unresolvable = checker.DynamicValue.fromComplexFunctionCall(node, fn);
3512
+ return context.foreignFunctionResolver(lhs, node, resolveFfrExpr, unresolvable);
3513
+ }
3514
+ return res;
3515
+ }
3516
+ /**
3517
+ * Visit an expression which was extracted from a foreign-function resolver.
3518
+ *
3519
+ * This will process the result and ensure it's correct for FFR-resolved values, including marking
3520
+ * `Reference`s as synthetic.
3521
+ */
3522
+ visitFfrExpression(expr, context) {
3523
+ const res = this.visitExpression(expr, context);
3524
+ if (res instanceof checker.Reference) {
3525
+ // This Reference was created synthetically, via a foreign function resolver. The real
3526
+ // runtime value of the function expression may be different than the foreign function
3527
+ // resolved value, so mark the Reference as synthetic to avoid it being misinterpreted.
3528
+ res.synthetic = true;
3529
+ }
3530
+ return res;
3531
+ }
3532
+ visitFunctionBody(node, fn, context) {
3533
+ if (fn.body === null) {
3534
+ return checker.DynamicValue.fromUnknown(node);
3535
+ }
3536
+ else if (fn.body.length !== 1 || !ts.isReturnStatement(fn.body[0])) {
3537
+ return checker.DynamicValue.fromComplexFunctionCall(node, fn);
3538
+ }
3539
+ const ret = fn.body[0];
3540
+ const args = this.evaluateFunctionArguments(node, context);
3541
+ const newScope = new Map();
3542
+ const calleeContext = { ...context, scope: newScope };
3543
+ fn.parameters.forEach((param, index) => {
3544
+ let arg = args[index];
3545
+ if (param.node.dotDotDotToken !== undefined) {
3546
+ arg = args.slice(index);
3547
+ }
3548
+ if (arg === undefined && param.initializer !== null) {
3549
+ arg = this.visitExpression(param.initializer, calleeContext);
3550
+ }
3551
+ newScope.set(param.node, arg);
3552
+ });
3553
+ return ret.expression !== undefined
3554
+ ? this.visitExpression(ret.expression, calleeContext)
3555
+ : undefined;
3556
+ }
3557
+ visitConditionalExpression(node, context) {
3558
+ const condition = this.visitExpression(node.condition, context);
3559
+ if (condition instanceof checker.DynamicValue) {
3560
+ return checker.DynamicValue.fromDynamicInput(node, condition);
3561
+ }
3562
+ if (condition) {
3563
+ return this.visitExpression(node.whenTrue, context);
3564
+ }
3565
+ else {
3566
+ return this.visitExpression(node.whenFalse, context);
3567
+ }
3568
+ }
3569
+ visitPrefixUnaryExpression(node, context) {
3570
+ const operatorKind = node.operator;
3571
+ if (!this.UNARY_OPERATORS.has(operatorKind)) {
3572
+ return checker.DynamicValue.fromUnsupportedSyntax(node);
3573
+ }
3574
+ const op = this.UNARY_OPERATORS.get(operatorKind);
3575
+ const value = this.visitExpression(node.operand, context);
3576
+ if (value instanceof checker.DynamicValue) {
3577
+ return checker.DynamicValue.fromDynamicInput(node, value);
3578
+ }
3579
+ else {
3580
+ return op(value);
3581
+ }
3582
+ }
3583
+ visitBinaryExpression(node, context) {
3584
+ const tokenKind = node.operatorToken.kind;
3585
+ if (!this.BINARY_OPERATORS.has(tokenKind)) {
3586
+ return checker.DynamicValue.fromUnsupportedSyntax(node);
3587
+ }
3588
+ const opRecord = this.BINARY_OPERATORS.get(tokenKind);
3589
+ let lhs, rhs;
3590
+ if (opRecord.literal) {
3591
+ lhs = literal(this.visitExpression(node.left, context), (value) => checker.DynamicValue.fromInvalidExpressionType(node.left, value));
3592
+ rhs = literal(this.visitExpression(node.right, context), (value) => checker.DynamicValue.fromInvalidExpressionType(node.right, value));
3593
+ }
3594
+ else {
3595
+ lhs = this.visitExpression(node.left, context);
3596
+ rhs = this.visitExpression(node.right, context);
3597
+ }
3598
+ if (lhs instanceof checker.DynamicValue) {
3599
+ return checker.DynamicValue.fromDynamicInput(node, lhs);
3600
+ }
3601
+ else if (rhs instanceof checker.DynamicValue) {
3602
+ return checker.DynamicValue.fromDynamicInput(node, rhs);
3603
+ }
3604
+ else {
3605
+ return opRecord.op(lhs, rhs);
3606
+ }
3607
+ }
3608
+ visitParenthesizedExpression(node, context) {
3609
+ return this.visitExpression(node.expression, context);
3610
+ }
3611
+ evaluateFunctionArguments(node, context) {
3612
+ const args = [];
3613
+ for (const arg of node.arguments) {
3614
+ if (ts.isSpreadElement(arg)) {
3615
+ args.push(...this.visitSpreadElement(arg, context));
3616
+ }
3617
+ else {
3618
+ args.push(this.visitExpression(arg, context));
3619
+ }
3620
+ }
3621
+ return args;
3622
+ }
3623
+ visitSpreadElement(node, context) {
3624
+ const spread = this.visitExpression(node.expression, context);
3625
+ if (spread instanceof checker.DynamicValue) {
3626
+ return [checker.DynamicValue.fromDynamicInput(node, spread)];
3627
+ }
3628
+ else if (!Array.isArray(spread)) {
3629
+ return [checker.DynamicValue.fromInvalidExpressionType(node, spread)];
3630
+ }
3631
+ else {
3632
+ return spread;
3633
+ }
3634
+ }
3635
+ visitBindingElement(node, context) {
3636
+ const path = [];
3637
+ let closestDeclaration = node;
3638
+ while (ts.isBindingElement(closestDeclaration) ||
3639
+ ts.isArrayBindingPattern(closestDeclaration) ||
3640
+ ts.isObjectBindingPattern(closestDeclaration)) {
3641
+ if (ts.isBindingElement(closestDeclaration)) {
3642
+ path.unshift(closestDeclaration);
3643
+ }
3644
+ closestDeclaration = closestDeclaration.parent;
3645
+ }
3646
+ if (!ts.isVariableDeclaration(closestDeclaration) ||
3647
+ closestDeclaration.initializer === undefined) {
3648
+ return checker.DynamicValue.fromUnknown(node);
3649
+ }
3650
+ let value = this.visit(closestDeclaration.initializer, context);
3651
+ for (const element of path) {
3652
+ let key;
3653
+ if (ts.isArrayBindingPattern(element.parent)) {
3654
+ key = element.parent.elements.indexOf(element);
3655
+ }
3656
+ else {
3657
+ const name = element.propertyName || element.name;
3658
+ if (ts.isIdentifier(name)) {
3659
+ key = name.text;
3660
+ }
3661
+ else {
3662
+ return checker.DynamicValue.fromUnknown(element);
3663
+ }
3664
+ }
3665
+ value = this.accessHelper(element, value, key, context);
3666
+ if (value instanceof checker.DynamicValue) {
3667
+ return value;
3668
+ }
3669
+ }
3670
+ return value;
3671
+ }
3672
+ stringNameFromPropertyName(node, context) {
3673
+ if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node)) {
3674
+ return node.text;
3675
+ }
3676
+ else if (ts.isComputedPropertyName(node)) {
3677
+ const literal = this.visitExpression(node.expression, context);
3678
+ return typeof literal === 'string' ? literal : undefined;
3679
+ }
3680
+ else {
3681
+ return undefined;
3682
+ }
3683
+ }
3684
+ getReference(node, context) {
3685
+ return new checker.Reference(node, owningModule(context));
3686
+ }
3687
+ visitType(node, context) {
3688
+ if (ts.isLiteralTypeNode(node)) {
3689
+ return this.visitExpression(node.literal, context);
3690
+ }
3691
+ else if (ts.isTupleTypeNode(node)) {
3692
+ return this.visitTupleType(node, context);
3693
+ }
3694
+ else if (ts.isNamedTupleMember(node)) {
3695
+ return this.visitType(node.type, context);
3696
+ }
3697
+ else if (ts.isTypeOperatorNode(node) && node.operator === ts.SyntaxKind.ReadonlyKeyword) {
3698
+ return this.visitType(node.type, context);
3699
+ }
3700
+ else if (ts.isTypeQueryNode(node)) {
3701
+ return this.visitTypeQuery(node, context);
3702
+ }
3703
+ return checker.DynamicValue.fromDynamicType(node);
3704
+ }
3705
+ visitTupleType(node, context) {
3706
+ const res = [];
3707
+ for (const elem of node.elements) {
3708
+ res.push(this.visitType(elem, context));
3709
+ }
3710
+ return res;
3711
+ }
3712
+ visitTypeQuery(node, context) {
3713
+ if (!ts.isIdentifier(node.exprName)) {
3714
+ return checker.DynamicValue.fromUnknown(node);
3715
+ }
3716
+ const decl = this.host.getDeclarationOfIdentifier(node.exprName);
3717
+ if (decl === null) {
3718
+ return checker.DynamicValue.fromUnknownIdentifier(node.exprName);
3719
+ }
3720
+ const declContext = { ...context, ...joinModuleContext(context, node, decl) };
3721
+ return this.visitDeclaration(decl.node, declContext);
3722
+ }
3723
+ }
3724
+ function isFunctionOrMethodReference(ref) {
3725
+ return (ts.isFunctionDeclaration(ref.node) ||
3726
+ ts.isMethodDeclaration(ref.node) ||
3727
+ ts.isFunctionExpression(ref.node));
3728
+ }
3729
+ function literal(value, reject) {
3730
+ if (value instanceof checker.EnumValue) {
3731
+ value = value.resolved;
3732
+ }
3733
+ if (value instanceof checker.DynamicValue ||
3734
+ value === null ||
3735
+ value === undefined ||
3736
+ typeof value === 'string' ||
3737
+ typeof value === 'number' ||
3738
+ typeof value === 'boolean') {
3739
+ return value;
3740
+ }
3741
+ return reject(value);
3742
+ }
3743
+ function isVariableDeclarationDeclared(node) {
3744
+ if (node.parent === undefined || !ts.isVariableDeclarationList(node.parent)) {
3745
+ return false;
3746
+ }
3747
+ const declList = node.parent;
3748
+ if (declList.parent === undefined || !ts.isVariableStatement(declList.parent)) {
3749
+ return false;
3750
+ }
3751
+ const varStmt = declList.parent;
3752
+ const modifiers = ts.getModifiers(varStmt);
3753
+ return (modifiers !== undefined && modifiers.some((mod) => mod.kind === ts.SyntaxKind.DeclareKeyword));
3754
+ }
3755
+ const EMPTY = {};
3756
+ function joinModuleContext(existing, node, decl) {
3757
+ if (typeof decl.viaModule === 'string' && decl.viaModule !== existing.absoluteModuleName) {
3758
+ return {
3759
+ absoluteModuleName: decl.viaModule,
3760
+ resolutionContext: node.getSourceFile().fileName,
3761
+ };
3762
+ }
3763
+ else {
3764
+ return EMPTY;
3765
+ }
3766
+ }
3767
+ function owningModule(context, override = null) {
3768
+ let specifier = context.absoluteModuleName;
3769
+ if (override !== null) {
3770
+ specifier = override.specifier;
3771
+ }
3772
+ if (specifier !== null) {
3773
+ return {
3774
+ specifier,
3775
+ resolutionContext: context.resolutionContext,
3776
+ };
3777
+ }
3778
+ else {
3779
+ return null;
3780
+ }
3781
+ }
3782
+
2999
3783
  class PartialEvaluator {
3000
3784
  host;
3001
3785
  checker;
@@ -3006,7 +3790,7 @@ class PartialEvaluator {
3006
3790
  this.dependencyTracker = dependencyTracker;
3007
3791
  }
3008
3792
  evaluate(expr, foreignFunctionResolver) {
3009
- const interpreter = new checker.StaticInterpreter(this.host, this.checker, this.dependencyTracker);
3793
+ const interpreter = new StaticInterpreter(this.host, this.checker, this.dependencyTracker);
3010
3794
  const sourceFile = expr.getSourceFile();
3011
3795
  return interpreter.visit(expr, {
3012
3796
  originatingFile: sourceFile,
@@ -7413,7 +8197,7 @@ function createModuleWithProvidersResolver(reflector, isCore) {
7413
8197
  if (!(ngModule instanceof checker.Reference) || !checker.isNamedClassDeclaration(ngModule.node)) {
7414
8198
  return unresolvable;
7415
8199
  }
7416
- return new checker.SyntheticValue({
8200
+ return new SyntheticValue({
7417
8201
  ngModule: ngModule,
7418
8202
  mwpCall: callExpr,
7419
8203
  });
@@ -8168,7 +8952,7 @@ class NgModuleDecoratorHandler {
8168
8952
  let entry = resolvedList[idx];
8169
8953
  // Unwrap ModuleWithProviders for modules that are locally declared (and thus static
8170
8954
  // resolution was able to descend into the function and return an object literal, a Map).
8171
- if (entry instanceof checker.SyntheticValue && isResolvedModuleWithProviders(entry)) {
8955
+ if (entry instanceof SyntheticValue && isResolvedModuleWithProviders(entry)) {
8172
8956
  entry = entry.value.ngModule;
8173
8957
  hasModuleWithProviders = true;
8174
8958
  }
@@ -8858,7 +9642,7 @@ function validateAndFlattenComponentImports(imports, expr, isDeferred) {
8858
9642
  }
8859
9643
  else if (isLikelyModuleWithProviders(ref)) {
8860
9644
  let origin = expr;
8861
- if (ref instanceof checker.SyntheticValue) {
9645
+ if (ref instanceof SyntheticValue) {
8862
9646
  // The `ModuleWithProviders` type originated from a foreign function declaration, in which
8863
9647
  // case the original foreign call is available which is used to get a more accurate origin
8864
9648
  // node that points at the specific call expression.
@@ -8901,7 +9685,7 @@ function validateAndFlattenComponentImports(imports, expr, isDeferred) {
8901
9685
  * key is considered a `ModuleWithProviders`.
8902
9686
  */
8903
9687
  function isLikelyModuleWithProviders(value) {
8904
- if (value instanceof checker.SyntheticValue && isResolvedModuleWithProviders(value)) {
9688
+ if (value instanceof SyntheticValue && isResolvedModuleWithProviders(value)) {
8905
9689
  // This is a `ModuleWithProviders` as extracted from a foreign function call.
8906
9690
  return true;
8907
9691
  }
@@ -11537,7 +12321,7 @@ class PipeDecoratorHandler {
11537
12321
  * @description
11538
12322
  * Entry point for all public APIs of the compiler-cli package.
11539
12323
  */
11540
- new checker.Version('20.1.0-rc.0');
12324
+ new checker.Version('20.2.0-next.0');
11541
12325
 
11542
12326
  /**
11543
12327
  * Whether a given decorator should be treated as an Angular decorator.
@@ -13444,11 +14228,18 @@ function extractLiteralPropertiesAsEnumMembers(declaration) {
13444
14228
 
13445
14229
  /** Extracts an API documentation entry for an Angular decorator. */
13446
14230
  function extractorDecorator(declaration, typeChecker) {
13447
- const documentedNode = getDecoratorJsDocNode(declaration);
14231
+ const documentedNode = getDecoratorJsDocNode(declaration, typeChecker);
13448
14232
  const decoratorType = getDecoratorType(declaration);
13449
14233
  if (!decoratorType) {
13450
14234
  throw new Error(`"${declaration.name.getText()} is not a decorator."`);
13451
14235
  }
14236
+ const members = getDecoratorProperties(declaration, typeChecker);
14237
+ let signatures = [];
14238
+ if (!members) {
14239
+ const decoratorInterface = getDecoratorDeclaration(declaration, typeChecker);
14240
+ const callSignatures = decoratorInterface.members.filter(ts.isCallSignatureDeclaration);
14241
+ signatures = getDecoratorSignatures(callSignatures, typeChecker);
14242
+ }
13452
14243
  return {
13453
14244
  name: declaration.name.getText(),
13454
14245
  decoratorType: decoratorType,
@@ -13456,7 +14247,8 @@ function extractorDecorator(declaration, typeChecker) {
13456
14247
  rawComment: extractRawJsDoc(documentedNode),
13457
14248
  description: extractJsDocDescription(documentedNode),
13458
14249
  jsdocTags: extractJsDocTags(documentedNode),
13459
- members: getDecoratorOptions(declaration, typeChecker),
14250
+ members,
14251
+ signatures,
13460
14252
  };
13461
14253
  }
13462
14254
  /** Gets whether the given variable declaration is an Angular decorator declaration. */
@@ -13483,35 +14275,77 @@ function getDecoratorType(declaration) {
13483
14275
  return DecoratorType.Parameter;
13484
14276
  return undefined;
13485
14277
  }
13486
- /** Gets the doc entry for the options object for an Angular decorator */
13487
- function getDecoratorOptions(declaration, typeChecker) {
13488
- const name = declaration.name.getText();
13489
- // Every decorator has an interface with its options in the same SourceFile.
13490
- // Queries, however, are defined as a type alias pointing to an interface.
13491
- const optionsDeclaration = declaration.getSourceFile().statements.find((node) => {
13492
- return ((ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)) &&
13493
- node.name.getText() === name);
13494
- });
13495
- if (!optionsDeclaration) {
13496
- throw new Error(`Decorator "${name}" has no corresponding options interface.`);
14278
+ function getDecoratorDeclaration(declaration, typeChecker) {
14279
+ const decoratorName = declaration.name.getText();
14280
+ const decoratorDeclaration = declaration;
14281
+ const decoratorType = typeChecker.getTypeAtLocation(decoratorDeclaration);
14282
+ const aliasDeclaration = decoratorType.getSymbol().getDeclarations()[0];
14283
+ const decoratorInterface = aliasDeclaration;
14284
+ if (!decoratorInterface || !ts.isInterfaceDeclaration(decoratorInterface)) {
14285
+ throw new Error(`No decorator interface found for "${decoratorName}".`);
13497
14286
  }
13498
- let optionsInterface;
13499
- if (ts.isTypeAliasDeclaration(optionsDeclaration)) {
13500
- // We hard-code the assumption that if the decorator's option type is a type alias,
13501
- // it resolves to a single interface (this is true for all query decorators at time of
13502
- // this writing).
13503
- const aliasedType = typeChecker.getTypeAtLocation(optionsDeclaration.type);
13504
- optionsInterface = (aliasedType.getSymbol()?.getDeclarations() ?? []).find((d) => ts.isInterfaceDeclaration(d));
14287
+ return decoratorInterface;
14288
+ }
14289
+ /**
14290
+ * @returns Interface properties for decorators that are akin to interfaces eg. @Component
14291
+ * else return null for decorators that are akin to functions eg. @Inject
14292
+ */
14293
+ function getDecoratorProperties(declaration, typeChecker) {
14294
+ // Some decorators like Component, Directive are basically interchangeable with a interface declaration.
14295
+ // We want to acount for that and treat them a such.
14296
+ // To determine which type of decorator we have, we check the type of the first parameter of its call signature
14297
+ const decoratorCallSig = getDecoratorJsDocNode(declaration, typeChecker);
14298
+ const decoratorFirstParam = decoratorCallSig.parameters[0];
14299
+ const firstParamType = typeChecker.getTypeAtLocation(decoratorFirstParam);
14300
+ let firstParamTypeDecl;
14301
+ if (firstParamType.isUnion()) {
14302
+ // If the first param is a union, we need to get the first type
14303
+ // This happens for example when the decorator param is optional (eg @Directive())
14304
+ const firstParamTypeUnion = firstParamType.types.find((t) => (t.flags & ts.TypeFlags.Undefined) === 0);
14305
+ firstParamTypeDecl = firstParamTypeUnion?.getSymbol()?.getDeclarations()[0];
13505
14306
  }
13506
14307
  else {
13507
- optionsInterface = optionsDeclaration;
14308
+ firstParamTypeDecl = firstParamType.getSymbol()?.getDeclarations()[0];
13508
14309
  }
13509
- if (!optionsInterface || !ts.isInterfaceDeclaration(optionsInterface)) {
13510
- throw new Error(`Options for decorator "${name}" is not an interface.`);
14310
+ if (!firstParamTypeDecl || !ts.isInterfaceDeclaration(firstParamTypeDecl)) {
14311
+ // At this point we either have on first param, eg for decorators without parameters
14312
+ // or we have a decorator that isn't akin to an interface
14313
+ // We will threat them as functions (in another function) and return null here
14314
+ return null;
13511
14315
  }
13512
- // Take advantage of the interface extractor to pull the appropriate member info.
13513
- // Hard code the knowledge that decorator options only have properties, never methods.
13514
- return extractInterface(optionsInterface, typeChecker).members;
14316
+ const interfaceDeclaration = firstParamTypeDecl;
14317
+ return extractInterface(interfaceDeclaration, typeChecker).members;
14318
+ }
14319
+ function getDecoratorSignatures(callSignatures, typeChecker) {
14320
+ return callSignatures.map((signatureDecl) => {
14321
+ return {
14322
+ parameters: extractParams(signatureDecl.parameters, typeChecker),
14323
+ jsdocTags: extractJsDocTags(signatureDecl),
14324
+ };
14325
+ });
14326
+ }
14327
+ function extractParams(params, typeChecker) {
14328
+ return params.map((param) => ({
14329
+ name: param.name.getText(),
14330
+ description: extractJsDocDescription(param),
14331
+ type: getParamTypeString(param, typeChecker),
14332
+ isOptional: !!(param.questionToken || param.initializer),
14333
+ isRestParam: !!param.dotDotDotToken,
14334
+ }));
14335
+ }
14336
+ /**
14337
+ * Find the the interface usually suffixed with "Decorator" that describes the decorator.
14338
+ */
14339
+ function getDecoratorInterface(declaration, typeChecker) {
14340
+ const name = declaration.name.getText();
14341
+ const symbol = typeChecker.getSymbolAtLocation(declaration.name);
14342
+ const decoratorType = typeChecker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration);
14343
+ // This is the interface xxxxDecorator
14344
+ const decoratorInterface = decoratorType.getSymbol()?.getDeclarations()[0];
14345
+ if (!decoratorInterface || !ts.isInterfaceDeclaration(decoratorInterface)) {
14346
+ throw new Error(`No decorator interface found for "${name}".`);
14347
+ }
14348
+ return decoratorInterface;
13515
14349
  }
13516
14350
  /**
13517
14351
  * Gets the call signature node that has the decorator's public JsDoc block.
@@ -13523,26 +14357,68 @@ function getDecoratorOptions(declaration, typeChecker) {
13523
14357
  *
13524
14358
  * For the description and JsDoc tags, we need the interface suffixed with "Decorator".
13525
14359
  */
13526
- function getDecoratorJsDocNode(declaration) {
14360
+ function getDecoratorJsDocNode(declaration, typeChecker) {
13527
14361
  const name = declaration.name.getText();
13528
- // Assume the existence of an interface in the same file with the same name
13529
- // suffixed with "Decorator".
13530
- const decoratorInterface = declaration.getSourceFile().statements.find((s) => {
13531
- return ts.isInterfaceDeclaration(s) && s.name.getText() === `${name}Decorator`;
13532
- });
13533
- if (!decoratorInterface || !ts.isInterfaceDeclaration(decoratorInterface)) {
13534
- throw new Error(`No interface "${name}Decorator" found.`);
13535
- }
14362
+ const decoratorInterface = getDecoratorInterface(declaration, typeChecker);
13536
14363
  // The public-facing JsDoc for each decorator is on one of its interface's call signatures.
13537
- const callSignature = decoratorInterface.members.find((node) => {
14364
+ const callSignature = decoratorInterface.members
14365
+ .filter((node) => {
13538
14366
  // The description block lives on one of the call signatures for this interface.
13539
14367
  return ts.isCallSignatureDeclaration(node) && extractRawJsDoc(node);
13540
- });
14368
+ })
14369
+ .at(-1); // Get the last one, as it is the most complete
13541
14370
  if (!callSignature || !ts.isCallSignatureDeclaration(callSignature)) {
13542
14371
  throw new Error(`No call signature with JsDoc on "${name}Decorator"`);
13543
14372
  }
13544
14373
  return callSignature;
13545
14374
  }
14375
+ /**
14376
+ * Advanced function to generate the type string (as single line) for a parameter.
14377
+ * Interfaces in unions are expanded.
14378
+ */
14379
+ function getParamTypeString(paramNode, typeChecker) {
14380
+ const type = typeChecker.getTypeAtLocation(paramNode);
14381
+ const printer = ts.createPrinter({ removeComments: true });
14382
+ const sourceFile = paramNode.getSourceFile();
14383
+ const replace = [];
14384
+ if (type.isUnion()) {
14385
+ // The parameter can be a union, this includes optional parameters whiceh are a union of the type and undefined.
14386
+ for (const subType of type.types) {
14387
+ const decl = subType.getSymbol()?.getDeclarations()?.[0];
14388
+ // We only care to expand interfaces
14389
+ if (decl && ts.isInterfaceDeclaration(decl) && decl.name.text !== 'Function') {
14390
+ // the Function type is actually an interface but we don't want to expand it
14391
+ replace.push({
14392
+ initial: subType.symbol.name,
14393
+ replacedWith: expandType(decl, sourceFile, printer),
14394
+ });
14395
+ }
14396
+ }
14397
+ }
14398
+ // Using a print here instead of typeToString as it doesn't return optional props as a union of undefined
14399
+ let result = printer
14400
+ .printNode(ts.EmitHint.Unspecified, paramNode, sourceFile)
14401
+ // Removing the parameter name, the conditional question mark and the colon (e.g. opts?: {foo: string})
14402
+ .replace(new RegExp(`${paramNode.name.getText()}\\??\: `), '')
14403
+ // Remove extra spaces/line breaks
14404
+ .replaceAll(/\s+/g, ' ');
14405
+ // Replace the types we expanded
14406
+ for (const { initial, replacedWith } of replace) {
14407
+ result = result.replace(initial, replacedWith);
14408
+ }
14409
+ return result;
14410
+ }
14411
+ /**
14412
+ * @return a given interface declaration as single line string
14413
+ */
14414
+ function expandType(decl, sourceFile, printer) {
14415
+ const props = decl.members
14416
+ // printer will return each member with a semicolon at the end
14417
+ .map((member) => printer.printNode(ts.EmitHint.Unspecified, member, sourceFile))
14418
+ .join(' ')
14419
+ .replaceAll(/\s+/g, ' '); // Remove extra spaces/line breaks
14420
+ return `{${props}}`;
14421
+ }
13546
14422
 
13547
14423
  /** Extracts documentation entry for an enum. */
13548
14424
  function extractEnum(declaration, typeChecker) {
@@ -19402,7 +20278,7 @@ var semver = /*@__PURE__*/getDefaultExportFromCjs(semverExports);
19402
20278
  * @param minVersion Minimum required version for the feature.
19403
20279
  */
19404
20280
  function coreVersionSupportsFeature(coreVersion, minVersion) {
19405
- // A version of `20.1.0-rc.0` usually means that core is at head so it supports
20281
+ // A version of `20.2.0-next.0` usually means that core is at head so it supports
19406
20282
  // all features. Use string interpolation prevent the placeholder from being replaced
19407
20283
  // with the current version during build time.
19408
20284
  if (coreVersion === `0.0.0-${'PLACEHOLDER'}`) {