@angular/compiler 19.1.4 → 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.4
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.4');
30803
+ const VERSION = new Version('19.1.6');
30767
30804
 
30768
30805
  class CompilerConfig {
30769
30806
  defaultEncapsulation;
@@ -32514,25 +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
- const locals = meta.localDependencies.map((localName) => variable(localName));
32524
32559
  const namespaces = meta.namespaceDependencies.map((dep) => {
32525
32560
  return new ExternalExpr({ moduleName: dep.moduleName, name: null });
32526
32561
  });
32527
32562
  // m.default
32528
32563
  const defaultRead = variable(moduleName).prop('default');
32529
- // ɵɵreplaceMetadata(Comp, m.default, [...namespaces], [...locals]);
32564
+ // ɵɵreplaceMetadata(Comp, m.default, [...namespaces], [...locals], import.meta, id);
32530
32565
  const replaceCall = importExpr(Identifiers.replaceMetadata)
32531
- .callFn([meta.type, defaultRead, literalArr(namespaces), literalArr(locals)]);
32566
+ .callFn([
32567
+ meta.type,
32568
+ defaultRead,
32569
+ literalArr(namespaces),
32570
+ literalArr(meta.localDependencies.map((l) => l.runtimeRepresentation)),
32571
+ variable('import').prop('meta'),
32572
+ variable(idName),
32573
+ ]);
32532
32574
  // (m) => m.default && ɵɵreplaceMetadata(...)
32533
32575
  const replaceCallback = arrowFn([new FnParam(moduleName)], defaultRead.and(replaceCall));
32534
- // '<urlPartial>' + encodeURIComponent(t)
32535
- 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='))
32536
32580
  .plus(variable('encodeURIComponent').callFn([variable(timestampName)]));
32537
32581
  // import.meta.url
32538
32582
  const urlBase = variable('import').prop('meta').prop('url');
@@ -32550,10 +32594,10 @@ function compileHmrInitializer(meta) {
32550
32594
  .callFn([replaceCallback])
32551
32595
  .toStmt(),
32552
32596
  ], null, StmtModifier.Final);
32553
- // (d) => d.id === <id> && Cmp_HmrLoad(d.timestamp)
32597
+ // (d) => d.id === id && Cmp_HmrLoad(d.timestamp)
32554
32598
  const updateCallback = arrowFn([new FnParam(dataName)], variable(dataName)
32555
32599
  .prop('id')
32556
- .identical(literal(id))
32600
+ .identical(variable(idName))
32557
32601
  .and(variable(importCallbackName).callFn([variable(dataName).prop('timestamp')])));
32558
32602
  // Cmp_HmrLoad(Date.now());
32559
32603
  // Initial call to kick off the loading in order to avoid edge cases with components
@@ -32568,6 +32612,8 @@ function compileHmrInitializer(meta) {
32568
32612
  .prop('on')
32569
32613
  .callFn([literal('angular:component-update'), updateCallback]);
32570
32614
  return arrowFn([], [
32615
+ // const id = <id>;
32616
+ new DeclareVarStmt(idName, literal(encodeURIComponent(`${meta.filePath}@${meta.className}`)), null, StmtModifier.Final),
32571
32617
  // function Cmp_HmrLoad() {...}.
32572
32618
  importCallback,
32573
32619
  // ngDevMode && Cmp_HmrLoad(Date.now());
@@ -32586,8 +32632,11 @@ function compileHmrInitializer(meta) {
32586
32632
  */
32587
32633
  function compileHmrUpdateCallback(definitions, constantStatements, meta) {
32588
32634
  const namespaces = 'ɵɵnamespaces';
32589
- const params = [meta.className, namespaces, ...meta.localDependencies].map((name) => new FnParam(name, DYNAMIC_TYPE));
32635
+ const params = [meta.className, namespaces].map((name) => new FnParam(name, DYNAMIC_TYPE));
32590
32636
  const body = [];
32637
+ for (const local of meta.localDependencies) {
32638
+ params.push(new FnParam(local.name));
32639
+ }
32591
32640
  // Declare variables that read out the individual namespaces.
32592
32641
  for (let i = 0; i < meta.namespaceDependencies.length; i++) {
32593
32642
  body.push(new DeclareVarStmt(meta.namespaceDependencies[i].assignedName, variable(namespaces).key(literal(i)), DYNAMIC_TYPE, StmtModifier.Final));
@@ -32619,7 +32668,7 @@ const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
32619
32668
  function compileDeclareClassMetadata(metadata) {
32620
32669
  const definitionMap = new DefinitionMap();
32621
32670
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
32622
- definitionMap.set('version', literal('19.1.4'));
32671
+ definitionMap.set('version', literal('19.1.6'));
32623
32672
  definitionMap.set('ngImport', importExpr(Identifiers.core));
32624
32673
  definitionMap.set('type', metadata.type);
32625
32674
  definitionMap.set('decorators', metadata.decorators);
@@ -32637,7 +32686,7 @@ function compileComponentDeclareClassMetadata(metadata, dependencies) {
32637
32686
  callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? literal(null));
32638
32687
  callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? literal(null));
32639
32688
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
32640
- definitionMap.set('version', literal('19.1.4'));
32689
+ definitionMap.set('version', literal('19.1.6'));
32641
32690
  definitionMap.set('ngImport', importExpr(Identifiers.core));
32642
32691
  definitionMap.set('type', metadata.type);
32643
32692
  definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
@@ -32732,7 +32781,7 @@ function createDirectiveDefinitionMap(meta) {
32732
32781
  const definitionMap = new DefinitionMap();
32733
32782
  const minVersion = getMinimumVersionForPartialOutput(meta);
32734
32783
  definitionMap.set('minVersion', literal(minVersion));
32735
- definitionMap.set('version', literal('19.1.4'));
32784
+ definitionMap.set('version', literal('19.1.6'));
32736
32785
  // e.g. `type: MyDirective`
32737
32786
  definitionMap.set('type', meta.type.value);
32738
32787
  if (meta.isStandalone !== undefined) {
@@ -33151,7 +33200,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
33151
33200
  function compileDeclareFactoryFunction(meta) {
33152
33201
  const definitionMap = new DefinitionMap();
33153
33202
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
33154
- definitionMap.set('version', literal('19.1.4'));
33203
+ definitionMap.set('version', literal('19.1.6'));
33155
33204
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33156
33205
  definitionMap.set('type', meta.type.value);
33157
33206
  definitionMap.set('deps', compileDependencies(meta.deps));
@@ -33186,7 +33235,7 @@ function compileDeclareInjectableFromMetadata(meta) {
33186
33235
  function createInjectableDefinitionMap(meta) {
33187
33236
  const definitionMap = new DefinitionMap();
33188
33237
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
33189
- definitionMap.set('version', literal('19.1.4'));
33238
+ definitionMap.set('version', literal('19.1.6'));
33190
33239
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33191
33240
  definitionMap.set('type', meta.type.value);
33192
33241
  // Only generate providedIn property if it has a non-null value
@@ -33237,7 +33286,7 @@ function compileDeclareInjectorFromMetadata(meta) {
33237
33286
  function createInjectorDefinitionMap(meta) {
33238
33287
  const definitionMap = new DefinitionMap();
33239
33288
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
33240
- definitionMap.set('version', literal('19.1.4'));
33289
+ definitionMap.set('version', literal('19.1.6'));
33241
33290
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33242
33291
  definitionMap.set('type', meta.type.value);
33243
33292
  definitionMap.set('providers', meta.providers);
@@ -33270,7 +33319,7 @@ function createNgModuleDefinitionMap(meta) {
33270
33319
  throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
33271
33320
  }
33272
33321
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
33273
- definitionMap.set('version', literal('19.1.4'));
33322
+ definitionMap.set('version', literal('19.1.6'));
33274
33323
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33275
33324
  definitionMap.set('type', meta.type.value);
33276
33325
  // We only generate the keys in the metadata if the arrays contain values.
@@ -33321,7 +33370,7 @@ function compileDeclarePipeFromMetadata(meta) {
33321
33370
  function createPipeDefinitionMap(meta) {
33322
33371
  const definitionMap = new DefinitionMap();
33323
33372
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
33324
- definitionMap.set('version', literal('19.1.4'));
33373
+ definitionMap.set('version', literal('19.1.6'));
33325
33374
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33326
33375
  // e.g. `type: MyPipe`
33327
33376
  definitionMap.set('type', meta.type.value);