@angular/compiler 19.1.5 → 19.1.6

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.6
3
3
  * (c) 2010-2024 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -10204,7 +10204,14 @@ function transformExpressionsInOp(op, transform, flags) {
10204
10204
  op.trustedValueFn && transformExpressionsInExpression(op.trustedValueFn, transform, flags);
10205
10205
  break;
10206
10206
  case OpKind.RepeaterCreate:
10207
- op.track = transformExpressionsInExpression(op.track, transform, flags);
10207
+ if (op.trackByOps === null) {
10208
+ op.track = transformExpressionsInExpression(op.track, transform, flags);
10209
+ }
10210
+ else {
10211
+ for (const innerOp of op.trackByOps) {
10212
+ transformExpressionsInOp(innerOp, transform, flags | VisitorContextFlag.InChildOperation);
10213
+ }
10214
+ }
10208
10215
  if (op.trackByFn !== null) {
10209
10216
  op.trackByFn = transformExpressionsInExpression(op.trackByFn, transform, flags);
10210
10217
  }
@@ -10732,6 +10739,7 @@ function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, em
10732
10739
  emptyView,
10733
10740
  track,
10734
10741
  trackByFn: null,
10742
+ trackByOps: null,
10735
10743
  tag,
10736
10744
  emptyTag,
10737
10745
  emptyAttributes: null,
@@ -11232,6 +11240,11 @@ class CompilationUnit {
11232
11240
  yield listenerOp;
11233
11241
  }
11234
11242
  }
11243
+ else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
11244
+ for (const trackOp of op.trackByOps) {
11245
+ yield trackOp;
11246
+ }
11247
+ }
11235
11248
  }
11236
11249
  for (const op of this.update) {
11237
11250
  yield op;
@@ -12964,6 +12977,9 @@ function recursivelyProcessView(view, parentScope) {
12964
12977
  if (op.emptyView) {
12965
12978
  recursivelyProcessView(view.job.views.get(op.emptyView), scope);
12966
12979
  }
12980
+ if (op.trackByOps !== null) {
12981
+ op.trackByOps.prepend(generateVariablesInScopeForView(view, scope, false));
12982
+ }
12967
12983
  break;
12968
12984
  case OpKind.Listener:
12969
12985
  case OpKind.TwoWayListener:
@@ -23079,7 +23095,7 @@ function reifyCreateOperations(unit, ops) {
23079
23095
  emptyDecls = emptyView.decls;
23080
23096
  emptyVars = emptyView.vars;
23081
23097
  }
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));
23098
+ 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
23099
  break;
23084
23100
  case OpKind.SourceLocation:
23085
23101
  const locationsLiteral = literalArr(op.locations.map(({ targetSlot, offset, line, column }) => {
@@ -23260,6 +23276,8 @@ function reifyIrExpression(expr) {
23260
23276
  return readContextLet(expr.targetSlot.slot);
23261
23277
  case ExpressionKind.StoreLet:
23262
23278
  return storeLet(expr.value, expr.sourceSpan);
23279
+ case ExpressionKind.TrackContext:
23280
+ return variable('this');
23263
23281
  default:
23264
23282
  throw new Error(`AssertionError: Unsupported reification of ir.Expression kind: ${ExpressionKind[expr.kind]}`);
23265
23283
  }
@@ -23288,6 +23306,42 @@ function reifyListenerHandler(unit, name, handlerOps, consumesDollarEvent) {
23288
23306
  }
23289
23307
  return fn(params, handlerStmts, undefined, undefined, name);
23290
23308
  }
23309
+ /** Reifies the tracking expression of a `RepeaterCreateOp`. */
23310
+ function reifyTrackBy(unit, op) {
23311
+ // If the tracking function was created already, there's nothing left to do.
23312
+ if (op.trackByFn !== null) {
23313
+ return op.trackByFn;
23314
+ }
23315
+ const params = [new FnParam('$index'), new FnParam('$item')];
23316
+ let fn$1;
23317
+ if (op.trackByOps === null) {
23318
+ // If there are no additional ops related to the tracking function, we just need
23319
+ // to turn it into a function that returns the result of the expression.
23320
+ fn$1 = op.usesComponentInstance
23321
+ ? fn(params, [new ReturnStatement(op.track)])
23322
+ : arrowFn(params, op.track);
23323
+ }
23324
+ else {
23325
+ // Otherwise first we need to reify the track-related ops.
23326
+ reifyUpdateOperations(unit, op.trackByOps);
23327
+ const statements = [];
23328
+ for (const trackOp of op.trackByOps) {
23329
+ if (trackOp.kind !== OpKind.Statement) {
23330
+ throw new Error(`AssertionError: expected reified statements, but found op ${OpKind[trackOp.kind]}`);
23331
+ }
23332
+ statements.push(trackOp.statement);
23333
+ }
23334
+ // Afterwards we can create the function from those ops.
23335
+ fn$1 =
23336
+ op.usesComponentInstance ||
23337
+ statements.length !== 1 ||
23338
+ !(statements[0] instanceof ReturnStatement)
23339
+ ? fn(params, statements)
23340
+ : arrowFn(params, statements[0].value);
23341
+ }
23342
+ op.trackByFn = unit.job.pool.getSharedFunctionReference(fn$1, '_forTrack');
23343
+ return op.trackByFn;
23344
+ }
23291
23345
 
23292
23346
  /**
23293
23347
  * Binding with no content can be safely deleted.
@@ -23386,6 +23440,11 @@ function processLexicalScope$1(view, ops) {
23386
23440
  case OpKind.TwoWayListener:
23387
23441
  processLexicalScope$1(view, op.handlerOps);
23388
23442
  break;
23443
+ case OpKind.RepeaterCreate:
23444
+ if (op.trackByOps !== null) {
23445
+ processLexicalScope$1(view, op.trackByOps);
23446
+ }
23447
+ break;
23389
23448
  }
23390
23449
  }
23391
23450
  if (view === view.job.root) {
@@ -23818,6 +23877,11 @@ function processLexicalScope(unit, ops, savedView) {
23818
23877
  // lexical scope.
23819
23878
  processLexicalScope(unit, op.handlerOps, savedView);
23820
23879
  break;
23880
+ case OpKind.RepeaterCreate:
23881
+ if (op.trackByOps !== null) {
23882
+ processLexicalScope(unit, op.trackByOps, savedView);
23883
+ }
23884
+ break;
23821
23885
  }
23822
23886
  }
23823
23887
  // Next, use the `scope` mapping to match `ir.LexicalReadExpr` with defined names in the lexical
@@ -24218,6 +24282,9 @@ function generateTemporaries(ops) {
24218
24282
  if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
24219
24283
  op.handlerOps.prepend(generateTemporaries(op.handlerOps));
24220
24284
  }
24285
+ else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
24286
+ op.trackByOps.prepend(generateTemporaries(op.trackByOps));
24287
+ }
24221
24288
  }
24222
24289
  return generatedStatements;
24223
24290
  }
@@ -24232,49 +24299,6 @@ function assignName(names, expr) {
24232
24299
  expr.name = name;
24233
24300
  }
24234
24301
 
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
24302
  /**
24279
24303
  * `track` functions in `for` repeaters can sometimes be "optimized," i.e. transformed into inline
24280
24304
  * expressions, in lieu of an external function call. For example, tracking by `$index` can be be
@@ -24321,12 +24345,20 @@ function optimizeTrackFns(job) {
24321
24345
  // Replace context reads with a special IR expression, since context reads in a track
24322
24346
  // function are emitted specially.
24323
24347
  op.track = transformExpressionsInExpression(op.track, (expr) => {
24324
- if (expr instanceof ContextExpr) {
24348
+ if (expr instanceof PipeBindingExpr || expr instanceof PipeBindingVariadicExpr) {
24349
+ throw new Error(`Illegal State: Pipes are not allowed in this context`);
24350
+ }
24351
+ else if (expr instanceof ContextExpr) {
24325
24352
  op.usesComponentInstance = true;
24326
24353
  return new TrackContextExpr(expr.view);
24327
24354
  }
24328
24355
  return expr;
24329
24356
  }, VisitorContextFlag.None);
24357
+ // Also create an OpList for the tracking expression since it may need
24358
+ // additional ops when generating the final code (e.g. temporary variables).
24359
+ const trackOpList = new OpList();
24360
+ trackOpList.push(createStatementOp(new ReturnStatement(op.track, op.track.sourceSpan)));
24361
+ op.trackByOps = trackOpList;
24330
24362
  }
24331
24363
  }
24332
24364
  }
@@ -24551,6 +24583,9 @@ function optimizeVariables(job) {
24551
24583
  if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
24552
24584
  inlineAlwaysInlineVariables(op.handlerOps);
24553
24585
  }
24586
+ else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
24587
+ inlineAlwaysInlineVariables(op.trackByOps);
24588
+ }
24554
24589
  }
24555
24590
  optimizeVariablesInOpList(unit.create, job.compatibility);
24556
24591
  optimizeVariablesInOpList(unit.update, job.compatibility);
@@ -24558,6 +24593,9 @@ function optimizeVariables(job) {
24558
24593
  if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
24559
24594
  optimizeVariablesInOpList(op.handlerOps, job.compatibility);
24560
24595
  }
24596
+ else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
24597
+ optimizeVariablesInOpList(op.trackByOps, job.compatibility);
24598
+ }
24561
24599
  }
24562
24600
  }
24563
24601
  }
@@ -25138,7 +25176,6 @@ const phases = [
25138
25176
  { kind: CompilationJobKind.Tmpl, fn: resolveI18nElementPlaceholders },
25139
25177
  { kind: CompilationJobKind.Tmpl, fn: resolveI18nExpressionPlaceholders },
25140
25178
  { kind: CompilationJobKind.Tmpl, fn: extractI18nMessages },
25141
- { kind: CompilationJobKind.Tmpl, fn: generateTrackFns },
25142
25179
  { kind: CompilationJobKind.Tmpl, fn: collectI18nConsts },
25143
25180
  { kind: CompilationJobKind.Tmpl, fn: collectConstExpressions },
25144
25181
  { kind: CompilationJobKind.Both, fn: collectElementConsts },
@@ -30763,7 +30800,7 @@ function publishFacade(global) {
30763
30800
  * @description
30764
30801
  * Entry point for all public APIs of the compiler package.
30765
30802
  */
30766
- const VERSION = new Version('19.1.5');
30803
+ const VERSION = new Version('19.1.6');
30767
30804
 
30768
30805
  class CompilerConfig {
30769
30806
  defaultEncapsulation;
@@ -32514,29 +32551,32 @@ function compileClassDebugInfo(debugInfo) {
32514
32551
  * @param meta HMR metadata extracted from the class.
32515
32552
  */
32516
32553
  function compileHmrInitializer(meta) {
32517
- const id = encodeURIComponent(`${meta.filePath}@${meta.className}`);
32518
- const urlPartial = `./@ng/component?c=${id}&t=`;
32519
32554
  const moduleName = 'm';
32520
32555
  const dataName = 'd';
32521
32556
  const timestampName = 't';
32557
+ const idName = 'id';
32522
32558
  const importCallbackName = `${meta.className}_HmrLoad`;
32523
32559
  const namespaces = meta.namespaceDependencies.map((dep) => {
32524
32560
  return new ExternalExpr({ moduleName: dep.moduleName, name: null });
32525
32561
  });
32526
32562
  // m.default
32527
32563
  const defaultRead = variable(moduleName).prop('default');
32528
- // ɵɵreplaceMetadata(Comp, m.default, [...namespaces], [...locals]);
32564
+ // ɵɵreplaceMetadata(Comp, m.default, [...namespaces], [...locals], import.meta, id);
32529
32565
  const replaceCall = importExpr(Identifiers.replaceMetadata)
32530
32566
  .callFn([
32531
32567
  meta.type,
32532
32568
  defaultRead,
32533
32569
  literalArr(namespaces),
32534
32570
  literalArr(meta.localDependencies.map((l) => l.runtimeRepresentation)),
32571
+ variable('import').prop('meta'),
32572
+ variable(idName),
32535
32573
  ]);
32536
32574
  // (m) => m.default && ɵɵreplaceMetadata(...)
32537
32575
  const replaceCallback = arrowFn([new FnParam(moduleName)], defaultRead.and(replaceCall));
32538
- // '<urlPartial>' + encodeURIComponent(t)
32539
- const urlValue = literal(urlPartial)
32576
+ // '<url>?c=' + id + '&t=' + encodeURIComponent(t)
32577
+ const urlValue = literal(`./@ng/component?c=`)
32578
+ .plus(variable(idName))
32579
+ .plus(literal('&t='))
32540
32580
  .plus(variable('encodeURIComponent').callFn([variable(timestampName)]));
32541
32581
  // import.meta.url
32542
32582
  const urlBase = variable('import').prop('meta').prop('url');
@@ -32554,10 +32594,10 @@ function compileHmrInitializer(meta) {
32554
32594
  .callFn([replaceCallback])
32555
32595
  .toStmt(),
32556
32596
  ], null, StmtModifier.Final);
32557
- // (d) => d.id === <id> && Cmp_HmrLoad(d.timestamp)
32597
+ // (d) => d.id === id && Cmp_HmrLoad(d.timestamp)
32558
32598
  const updateCallback = arrowFn([new FnParam(dataName)], variable(dataName)
32559
32599
  .prop('id')
32560
- .identical(literal(id))
32600
+ .identical(variable(idName))
32561
32601
  .and(variable(importCallbackName).callFn([variable(dataName).prop('timestamp')])));
32562
32602
  // Cmp_HmrLoad(Date.now());
32563
32603
  // Initial call to kick off the loading in order to avoid edge cases with components
@@ -32572,6 +32612,8 @@ function compileHmrInitializer(meta) {
32572
32612
  .prop('on')
32573
32613
  .callFn([literal('angular:component-update'), updateCallback]);
32574
32614
  return arrowFn([], [
32615
+ // const id = <id>;
32616
+ new DeclareVarStmt(idName, literal(encodeURIComponent(`${meta.filePath}@${meta.className}`)), null, StmtModifier.Final),
32575
32617
  // function Cmp_HmrLoad() {...}.
32576
32618
  importCallback,
32577
32619
  // ngDevMode && Cmp_HmrLoad(Date.now());
@@ -32626,7 +32668,7 @@ const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
32626
32668
  function compileDeclareClassMetadata(metadata) {
32627
32669
  const definitionMap = new DefinitionMap();
32628
32670
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
32629
- definitionMap.set('version', literal('19.1.5'));
32671
+ definitionMap.set('version', literal('19.1.6'));
32630
32672
  definitionMap.set('ngImport', importExpr(Identifiers.core));
32631
32673
  definitionMap.set('type', metadata.type);
32632
32674
  definitionMap.set('decorators', metadata.decorators);
@@ -32644,7 +32686,7 @@ function compileComponentDeclareClassMetadata(metadata, dependencies) {
32644
32686
  callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? literal(null));
32645
32687
  callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? literal(null));
32646
32688
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
32647
- definitionMap.set('version', literal('19.1.5'));
32689
+ definitionMap.set('version', literal('19.1.6'));
32648
32690
  definitionMap.set('ngImport', importExpr(Identifiers.core));
32649
32691
  definitionMap.set('type', metadata.type);
32650
32692
  definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
@@ -32739,7 +32781,7 @@ function createDirectiveDefinitionMap(meta) {
32739
32781
  const definitionMap = new DefinitionMap();
32740
32782
  const minVersion = getMinimumVersionForPartialOutput(meta);
32741
32783
  definitionMap.set('minVersion', literal(minVersion));
32742
- definitionMap.set('version', literal('19.1.5'));
32784
+ definitionMap.set('version', literal('19.1.6'));
32743
32785
  // e.g. `type: MyDirective`
32744
32786
  definitionMap.set('type', meta.type.value);
32745
32787
  if (meta.isStandalone !== undefined) {
@@ -33158,7 +33200,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
33158
33200
  function compileDeclareFactoryFunction(meta) {
33159
33201
  const definitionMap = new DefinitionMap();
33160
33202
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
33161
- definitionMap.set('version', literal('19.1.5'));
33203
+ definitionMap.set('version', literal('19.1.6'));
33162
33204
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33163
33205
  definitionMap.set('type', meta.type.value);
33164
33206
  definitionMap.set('deps', compileDependencies(meta.deps));
@@ -33193,7 +33235,7 @@ function compileDeclareInjectableFromMetadata(meta) {
33193
33235
  function createInjectableDefinitionMap(meta) {
33194
33236
  const definitionMap = new DefinitionMap();
33195
33237
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
33196
- definitionMap.set('version', literal('19.1.5'));
33238
+ definitionMap.set('version', literal('19.1.6'));
33197
33239
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33198
33240
  definitionMap.set('type', meta.type.value);
33199
33241
  // Only generate providedIn property if it has a non-null value
@@ -33244,7 +33286,7 @@ function compileDeclareInjectorFromMetadata(meta) {
33244
33286
  function createInjectorDefinitionMap(meta) {
33245
33287
  const definitionMap = new DefinitionMap();
33246
33288
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
33247
- definitionMap.set('version', literal('19.1.5'));
33289
+ definitionMap.set('version', literal('19.1.6'));
33248
33290
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33249
33291
  definitionMap.set('type', meta.type.value);
33250
33292
  definitionMap.set('providers', meta.providers);
@@ -33277,7 +33319,7 @@ function createNgModuleDefinitionMap(meta) {
33277
33319
  throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
33278
33320
  }
33279
33321
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
33280
- definitionMap.set('version', literal('19.1.5'));
33322
+ definitionMap.set('version', literal('19.1.6'));
33281
33323
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33282
33324
  definitionMap.set('type', meta.type.value);
33283
33325
  // We only generate the keys in the metadata if the arrays contain values.
@@ -33328,7 +33370,7 @@ function compileDeclarePipeFromMetadata(meta) {
33328
33370
  function createPipeDefinitionMap(meta) {
33329
33371
  const definitionMap = new DefinitionMap();
33330
33372
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
33331
- definitionMap.set('version', literal('19.1.5'));
33373
+ definitionMap.set('version', literal('19.1.6'));
33332
33374
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33333
33375
  // e.g. `type: MyPipe`
33334
33376
  definitionMap.set('type', meta.type.value);