@angular/compiler 19.1.5 → 19.1.7

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v19.1.5
2
+ * @license Angular v19.1.7
3
3
  * (c) 2010-2024 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -3032,10 +3032,6 @@ class Identifiers {
3032
3032
  name: 'ɵɵHostDirectivesFeature',
3033
3033
  moduleName: CORE,
3034
3034
  };
3035
- static InputTransformsFeatureFeature = {
3036
- name: 'ɵɵInputTransformsFeature',
3037
- moduleName: CORE,
3038
- };
3039
3035
  static ExternalStylesFeature = {
3040
3036
  name: 'ɵɵExternalStylesFeature',
3041
3037
  moduleName: CORE,
@@ -10204,7 +10200,14 @@ function transformExpressionsInOp(op, transform, flags) {
10204
10200
  op.trustedValueFn && transformExpressionsInExpression(op.trustedValueFn, transform, flags);
10205
10201
  break;
10206
10202
  case OpKind.RepeaterCreate:
10207
- op.track = transformExpressionsInExpression(op.track, transform, flags);
10203
+ if (op.trackByOps === null) {
10204
+ op.track = transformExpressionsInExpression(op.track, transform, flags);
10205
+ }
10206
+ else {
10207
+ for (const innerOp of op.trackByOps) {
10208
+ transformExpressionsInOp(innerOp, transform, flags | VisitorContextFlag.InChildOperation);
10209
+ }
10210
+ }
10208
10211
  if (op.trackByFn !== null) {
10209
10212
  op.trackByFn = transformExpressionsInExpression(op.trackByFn, transform, flags);
10210
10213
  }
@@ -10732,6 +10735,7 @@ function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, em
10732
10735
  emptyView,
10733
10736
  track,
10734
10737
  trackByFn: null,
10738
+ trackByOps: null,
10735
10739
  tag,
10736
10740
  emptyTag,
10737
10741
  emptyAttributes: null,
@@ -11232,6 +11236,11 @@ class CompilationUnit {
11232
11236
  yield listenerOp;
11233
11237
  }
11234
11238
  }
11239
+ else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
11240
+ for (const trackOp of op.trackByOps) {
11241
+ yield trackOp;
11242
+ }
11243
+ }
11235
11244
  }
11236
11245
  for (const op of this.update) {
11237
11246
  yield op;
@@ -12964,6 +12973,9 @@ function recursivelyProcessView(view, parentScope) {
12964
12973
  if (op.emptyView) {
12965
12974
  recursivelyProcessView(view.job.views.get(op.emptyView), scope);
12966
12975
  }
12976
+ if (op.trackByOps !== null) {
12977
+ op.trackByOps.prepend(generateVariablesInScopeForView(view, scope, false));
12978
+ }
12967
12979
  break;
12968
12980
  case OpKind.Listener:
12969
12981
  case OpKind.TwoWayListener:
@@ -23079,7 +23091,7 @@ function reifyCreateOperations(unit, ops) {
23079
23091
  emptyDecls = emptyView.decls;
23080
23092
  emptyVars = emptyView.vars;
23081
23093
  }
23082
- OpList.replace(op, repeaterCreate(op.handle.slot, repeaterView.fnName, op.decls, op.vars, op.tag, op.attributes, op.trackByFn, op.usesComponentInstance, emptyViewFnName, emptyDecls, emptyVars, op.emptyTag, op.emptyAttributes, op.wholeSourceSpan));
23094
+ OpList.replace(op, repeaterCreate(op.handle.slot, repeaterView.fnName, op.decls, op.vars, op.tag, op.attributes, reifyTrackBy(unit, op), op.usesComponentInstance, emptyViewFnName, emptyDecls, emptyVars, op.emptyTag, op.emptyAttributes, op.wholeSourceSpan));
23083
23095
  break;
23084
23096
  case OpKind.SourceLocation:
23085
23097
  const locationsLiteral = literalArr(op.locations.map(({ targetSlot, offset, line, column }) => {
@@ -23260,6 +23272,8 @@ function reifyIrExpression(expr) {
23260
23272
  return readContextLet(expr.targetSlot.slot);
23261
23273
  case ExpressionKind.StoreLet:
23262
23274
  return storeLet(expr.value, expr.sourceSpan);
23275
+ case ExpressionKind.TrackContext:
23276
+ return variable('this');
23263
23277
  default:
23264
23278
  throw new Error(`AssertionError: Unsupported reification of ir.Expression kind: ${ExpressionKind[expr.kind]}`);
23265
23279
  }
@@ -23288,6 +23302,42 @@ function reifyListenerHandler(unit, name, handlerOps, consumesDollarEvent) {
23288
23302
  }
23289
23303
  return fn(params, handlerStmts, undefined, undefined, name);
23290
23304
  }
23305
+ /** Reifies the tracking expression of a `RepeaterCreateOp`. */
23306
+ function reifyTrackBy(unit, op) {
23307
+ // If the tracking function was created already, there's nothing left to do.
23308
+ if (op.trackByFn !== null) {
23309
+ return op.trackByFn;
23310
+ }
23311
+ const params = [new FnParam('$index'), new FnParam('$item')];
23312
+ let fn$1;
23313
+ if (op.trackByOps === null) {
23314
+ // If there are no additional ops related to the tracking function, we just need
23315
+ // to turn it into a function that returns the result of the expression.
23316
+ fn$1 = op.usesComponentInstance
23317
+ ? fn(params, [new ReturnStatement(op.track)])
23318
+ : arrowFn(params, op.track);
23319
+ }
23320
+ else {
23321
+ // Otherwise first we need to reify the track-related ops.
23322
+ reifyUpdateOperations(unit, op.trackByOps);
23323
+ const statements = [];
23324
+ for (const trackOp of op.trackByOps) {
23325
+ if (trackOp.kind !== OpKind.Statement) {
23326
+ throw new Error(`AssertionError: expected reified statements, but found op ${OpKind[trackOp.kind]}`);
23327
+ }
23328
+ statements.push(trackOp.statement);
23329
+ }
23330
+ // Afterwards we can create the function from those ops.
23331
+ fn$1 =
23332
+ op.usesComponentInstance ||
23333
+ statements.length !== 1 ||
23334
+ !(statements[0] instanceof ReturnStatement)
23335
+ ? fn(params, statements)
23336
+ : arrowFn(params, statements[0].value);
23337
+ }
23338
+ op.trackByFn = unit.job.pool.getSharedFunctionReference(fn$1, '_forTrack');
23339
+ return op.trackByFn;
23340
+ }
23291
23341
 
23292
23342
  /**
23293
23343
  * Binding with no content can be safely deleted.
@@ -23386,6 +23436,11 @@ function processLexicalScope$1(view, ops) {
23386
23436
  case OpKind.TwoWayListener:
23387
23437
  processLexicalScope$1(view, op.handlerOps);
23388
23438
  break;
23439
+ case OpKind.RepeaterCreate:
23440
+ if (op.trackByOps !== null) {
23441
+ processLexicalScope$1(view, op.trackByOps);
23442
+ }
23443
+ break;
23389
23444
  }
23390
23445
  }
23391
23446
  if (view === view.job.root) {
@@ -23818,6 +23873,11 @@ function processLexicalScope(unit, ops, savedView) {
23818
23873
  // lexical scope.
23819
23874
  processLexicalScope(unit, op.handlerOps, savedView);
23820
23875
  break;
23876
+ case OpKind.RepeaterCreate:
23877
+ if (op.trackByOps !== null) {
23878
+ processLexicalScope(unit, op.trackByOps, savedView);
23879
+ }
23880
+ break;
23821
23881
  }
23822
23882
  }
23823
23883
  // Next, use the `scope` mapping to match `ir.LexicalReadExpr` with defined names in the lexical
@@ -24218,6 +24278,9 @@ function generateTemporaries(ops) {
24218
24278
  if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
24219
24279
  op.handlerOps.prepend(generateTemporaries(op.handlerOps));
24220
24280
  }
24281
+ else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
24282
+ op.trackByOps.prepend(generateTemporaries(op.trackByOps));
24283
+ }
24221
24284
  }
24222
24285
  return generatedStatements;
24223
24286
  }
@@ -24232,49 +24295,6 @@ function assignName(names, expr) {
24232
24295
  expr.name = name;
24233
24296
  }
24234
24297
 
24235
- /**
24236
- * Generate track functions that need to be extracted to the constant pool. This entails wrapping
24237
- * them in an arrow (or traditional) function, replacing context reads with `this.`, and storing
24238
- * them in the constant pool.
24239
- *
24240
- * Note that, if a track function was previously optimized, it will not need to be extracted, and
24241
- * this phase is a no-op.
24242
- */
24243
- function generateTrackFns(job) {
24244
- for (const unit of job.units) {
24245
- for (const op of unit.create) {
24246
- if (op.kind !== OpKind.RepeaterCreate) {
24247
- continue;
24248
- }
24249
- if (op.trackByFn !== null) {
24250
- // The final track function was already set, probably because it was optimized.
24251
- continue;
24252
- }
24253
- // Find all component context reads.
24254
- let usesComponentContext = false;
24255
- op.track = transformExpressionsInExpression(op.track, (expr) => {
24256
- if (expr instanceof PipeBindingExpr || expr instanceof PipeBindingVariadicExpr) {
24257
- throw new Error(`Illegal State: Pipes are not allowed in this context`);
24258
- }
24259
- if (expr instanceof TrackContextExpr) {
24260
- usesComponentContext = true;
24261
- return variable('this');
24262
- }
24263
- return expr;
24264
- }, VisitorContextFlag.None);
24265
- let fn;
24266
- const fnParams = [new FnParam('$index'), new FnParam('$item')];
24267
- if (usesComponentContext) {
24268
- fn = new FunctionExpr(fnParams, [new ReturnStatement(op.track)]);
24269
- }
24270
- else {
24271
- fn = arrowFn(fnParams, op.track);
24272
- }
24273
- op.trackByFn = job.pool.getSharedFunctionReference(fn, '_forTrack');
24274
- }
24275
- }
24276
- }
24277
-
24278
24298
  /**
24279
24299
  * `track` functions in `for` repeaters can sometimes be "optimized," i.e. transformed into inline
24280
24300
  * expressions, in lieu of an external function call. For example, tracking by `$index` can be be
@@ -24321,12 +24341,20 @@ function optimizeTrackFns(job) {
24321
24341
  // Replace context reads with a special IR expression, since context reads in a track
24322
24342
  // function are emitted specially.
24323
24343
  op.track = transformExpressionsInExpression(op.track, (expr) => {
24324
- if (expr instanceof ContextExpr) {
24344
+ if (expr instanceof PipeBindingExpr || expr instanceof PipeBindingVariadicExpr) {
24345
+ throw new Error(`Illegal State: Pipes are not allowed in this context`);
24346
+ }
24347
+ else if (expr instanceof ContextExpr) {
24325
24348
  op.usesComponentInstance = true;
24326
24349
  return new TrackContextExpr(expr.view);
24327
24350
  }
24328
24351
  return expr;
24329
24352
  }, VisitorContextFlag.None);
24353
+ // Also create an OpList for the tracking expression since it may need
24354
+ // additional ops when generating the final code (e.g. temporary variables).
24355
+ const trackOpList = new OpList();
24356
+ trackOpList.push(createStatementOp(new ReturnStatement(op.track, op.track.sourceSpan)));
24357
+ op.trackByOps = trackOpList;
24330
24358
  }
24331
24359
  }
24332
24360
  }
@@ -24551,6 +24579,9 @@ function optimizeVariables(job) {
24551
24579
  if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
24552
24580
  inlineAlwaysInlineVariables(op.handlerOps);
24553
24581
  }
24582
+ else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
24583
+ inlineAlwaysInlineVariables(op.trackByOps);
24584
+ }
24554
24585
  }
24555
24586
  optimizeVariablesInOpList(unit.create, job.compatibility);
24556
24587
  optimizeVariablesInOpList(unit.update, job.compatibility);
@@ -24558,6 +24589,9 @@ function optimizeVariables(job) {
24558
24589
  if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
24559
24590
  optimizeVariablesInOpList(op.handlerOps, job.compatibility);
24560
24591
  }
24592
+ else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
24593
+ optimizeVariablesInOpList(op.trackByOps, job.compatibility);
24594
+ }
24561
24595
  }
24562
24596
  }
24563
24597
  }
@@ -25138,7 +25172,6 @@ const phases = [
25138
25172
  { kind: CompilationJobKind.Tmpl, fn: resolveI18nElementPlaceholders },
25139
25173
  { kind: CompilationJobKind.Tmpl, fn: resolveI18nExpressionPlaceholders },
25140
25174
  { kind: CompilationJobKind.Tmpl, fn: extractI18nMessages },
25141
- { kind: CompilationJobKind.Tmpl, fn: generateTrackFns },
25142
25175
  { kind: CompilationJobKind.Tmpl, fn: collectI18nConsts },
25143
25176
  { kind: CompilationJobKind.Tmpl, fn: collectConstExpressions },
25144
25177
  { kind: CompilationJobKind.Both, fn: collectElementConsts },
@@ -28696,7 +28729,6 @@ function addFeatures(definitionMap, meta) {
28696
28729
  const features = [];
28697
28730
  const providers = meta.providers;
28698
28731
  const viewProviders = meta.viewProviders;
28699
- const inputKeys = Object.keys(meta.inputs);
28700
28732
  if (providers || viewProviders) {
28701
28733
  const args = [providers || new LiteralArrayExpr([])];
28702
28734
  if (viewProviders) {
@@ -28704,12 +28736,6 @@ function addFeatures(definitionMap, meta) {
28704
28736
  }
28705
28737
  features.push(importExpr(Identifiers.ProvidersFeature).callFn(args));
28706
28738
  }
28707
- for (const key of inputKeys) {
28708
- if (meta.inputs[key].transformFunction !== null) {
28709
- features.push(importExpr(Identifiers.InputTransformsFeatureFeature));
28710
- break;
28711
- }
28712
- }
28713
28739
  // Note: host directives feature needs to be inserted before the
28714
28740
  // inheritance feature to ensure the correct execution order.
28715
28741
  if (meta.hostDirectives?.length) {
@@ -30763,7 +30789,7 @@ function publishFacade(global) {
30763
30789
  * @description
30764
30790
  * Entry point for all public APIs of the compiler package.
30765
30791
  */
30766
- const VERSION = new Version('19.1.5');
30792
+ const VERSION = new Version('19.1.7');
30767
30793
 
30768
30794
  class CompilerConfig {
30769
30795
  defaultEncapsulation;
@@ -32514,29 +32540,32 @@ function compileClassDebugInfo(debugInfo) {
32514
32540
  * @param meta HMR metadata extracted from the class.
32515
32541
  */
32516
32542
  function compileHmrInitializer(meta) {
32517
- const id = encodeURIComponent(`${meta.filePath}@${meta.className}`);
32518
- const urlPartial = `./@ng/component?c=${id}&t=`;
32519
32543
  const moduleName = 'm';
32520
32544
  const dataName = 'd';
32521
32545
  const timestampName = 't';
32546
+ const idName = 'id';
32522
32547
  const importCallbackName = `${meta.className}_HmrLoad`;
32523
32548
  const namespaces = meta.namespaceDependencies.map((dep) => {
32524
32549
  return new ExternalExpr({ moduleName: dep.moduleName, name: null });
32525
32550
  });
32526
32551
  // m.default
32527
32552
  const defaultRead = variable(moduleName).prop('default');
32528
- // ɵɵreplaceMetadata(Comp, m.default, [...namespaces], [...locals]);
32553
+ // ɵɵreplaceMetadata(Comp, m.default, [...namespaces], [...locals], import.meta, id);
32529
32554
  const replaceCall = importExpr(Identifiers.replaceMetadata)
32530
32555
  .callFn([
32531
32556
  meta.type,
32532
32557
  defaultRead,
32533
32558
  literalArr(namespaces),
32534
32559
  literalArr(meta.localDependencies.map((l) => l.runtimeRepresentation)),
32560
+ variable('import').prop('meta'),
32561
+ variable(idName),
32535
32562
  ]);
32536
32563
  // (m) => m.default && ɵɵreplaceMetadata(...)
32537
32564
  const replaceCallback = arrowFn([new FnParam(moduleName)], defaultRead.and(replaceCall));
32538
- // '<urlPartial>' + encodeURIComponent(t)
32539
- const urlValue = literal(urlPartial)
32565
+ // '<url>?c=' + id + '&t=' + encodeURIComponent(t)
32566
+ const urlValue = literal(`./@ng/component?c=`)
32567
+ .plus(variable(idName))
32568
+ .plus(literal('&t='))
32540
32569
  .plus(variable('encodeURIComponent').callFn([variable(timestampName)]));
32541
32570
  // import.meta.url
32542
32571
  const urlBase = variable('import').prop('meta').prop('url');
@@ -32554,10 +32583,10 @@ function compileHmrInitializer(meta) {
32554
32583
  .callFn([replaceCallback])
32555
32584
  .toStmt(),
32556
32585
  ], null, StmtModifier.Final);
32557
- // (d) => d.id === <id> && Cmp_HmrLoad(d.timestamp)
32586
+ // (d) => d.id === id && Cmp_HmrLoad(d.timestamp)
32558
32587
  const updateCallback = arrowFn([new FnParam(dataName)], variable(dataName)
32559
32588
  .prop('id')
32560
- .identical(literal(id))
32589
+ .identical(variable(idName))
32561
32590
  .and(variable(importCallbackName).callFn([variable(dataName).prop('timestamp')])));
32562
32591
  // Cmp_HmrLoad(Date.now());
32563
32592
  // Initial call to kick off the loading in order to avoid edge cases with components
@@ -32572,6 +32601,8 @@ function compileHmrInitializer(meta) {
32572
32601
  .prop('on')
32573
32602
  .callFn([literal('angular:component-update'), updateCallback]);
32574
32603
  return arrowFn([], [
32604
+ // const id = <id>;
32605
+ new DeclareVarStmt(idName, literal(encodeURIComponent(`${meta.filePath}@${meta.className}`)), null, StmtModifier.Final),
32575
32606
  // function Cmp_HmrLoad() {...}.
32576
32607
  importCallback,
32577
32608
  // ngDevMode && Cmp_HmrLoad(Date.now());
@@ -32626,7 +32657,7 @@ const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
32626
32657
  function compileDeclareClassMetadata(metadata) {
32627
32658
  const definitionMap = new DefinitionMap();
32628
32659
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
32629
- definitionMap.set('version', literal('19.1.5'));
32660
+ definitionMap.set('version', literal('19.1.7'));
32630
32661
  definitionMap.set('ngImport', importExpr(Identifiers.core));
32631
32662
  definitionMap.set('type', metadata.type);
32632
32663
  definitionMap.set('decorators', metadata.decorators);
@@ -32644,7 +32675,7 @@ function compileComponentDeclareClassMetadata(metadata, dependencies) {
32644
32675
  callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? literal(null));
32645
32676
  callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? literal(null));
32646
32677
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
32647
- definitionMap.set('version', literal('19.1.5'));
32678
+ definitionMap.set('version', literal('19.1.7'));
32648
32679
  definitionMap.set('ngImport', importExpr(Identifiers.core));
32649
32680
  definitionMap.set('type', metadata.type);
32650
32681
  definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
@@ -32739,7 +32770,7 @@ function createDirectiveDefinitionMap(meta) {
32739
32770
  const definitionMap = new DefinitionMap();
32740
32771
  const minVersion = getMinimumVersionForPartialOutput(meta);
32741
32772
  definitionMap.set('minVersion', literal(minVersion));
32742
- definitionMap.set('version', literal('19.1.5'));
32773
+ definitionMap.set('version', literal('19.1.7'));
32743
32774
  // e.g. `type: MyDirective`
32744
32775
  definitionMap.set('type', meta.type.value);
32745
32776
  if (meta.isStandalone !== undefined) {
@@ -33158,7 +33189,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
33158
33189
  function compileDeclareFactoryFunction(meta) {
33159
33190
  const definitionMap = new DefinitionMap();
33160
33191
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
33161
- definitionMap.set('version', literal('19.1.5'));
33192
+ definitionMap.set('version', literal('19.1.7'));
33162
33193
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33163
33194
  definitionMap.set('type', meta.type.value);
33164
33195
  definitionMap.set('deps', compileDependencies(meta.deps));
@@ -33193,7 +33224,7 @@ function compileDeclareInjectableFromMetadata(meta) {
33193
33224
  function createInjectableDefinitionMap(meta) {
33194
33225
  const definitionMap = new DefinitionMap();
33195
33226
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
33196
- definitionMap.set('version', literal('19.1.5'));
33227
+ definitionMap.set('version', literal('19.1.7'));
33197
33228
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33198
33229
  definitionMap.set('type', meta.type.value);
33199
33230
  // Only generate providedIn property if it has a non-null value
@@ -33244,7 +33275,7 @@ function compileDeclareInjectorFromMetadata(meta) {
33244
33275
  function createInjectorDefinitionMap(meta) {
33245
33276
  const definitionMap = new DefinitionMap();
33246
33277
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
33247
- definitionMap.set('version', literal('19.1.5'));
33278
+ definitionMap.set('version', literal('19.1.7'));
33248
33279
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33249
33280
  definitionMap.set('type', meta.type.value);
33250
33281
  definitionMap.set('providers', meta.providers);
@@ -33277,7 +33308,7 @@ function createNgModuleDefinitionMap(meta) {
33277
33308
  throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
33278
33309
  }
33279
33310
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
33280
- definitionMap.set('version', literal('19.1.5'));
33311
+ definitionMap.set('version', literal('19.1.7'));
33281
33312
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33282
33313
  definitionMap.set('type', meta.type.value);
33283
33314
  // We only generate the keys in the metadata if the arrays contain values.
@@ -33328,7 +33359,7 @@ function compileDeclarePipeFromMetadata(meta) {
33328
33359
  function createPipeDefinitionMap(meta) {
33329
33360
  const definitionMap = new DefinitionMap();
33330
33361
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
33331
- definitionMap.set('version', literal('19.1.5'));
33362
+ definitionMap.set('version', literal('19.1.7'));
33332
33363
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33333
33364
  // e.g. `type: MyPipe`
33334
33365
  definitionMap.set('type', meta.type.value);