@angular/compiler 19.2.0-next.2 → 19.2.0-next.3

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.2.0-next.2
2
+ * @license Angular v19.2.0-next.3
3
3
  * (c) 2010-2024 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -10292,7 +10292,14 @@ function transformExpressionsInOp(op, transform, flags) {
10292
10292
  op.trustedValueFn && transformExpressionsInExpression(op.trustedValueFn, transform, flags);
10293
10293
  break;
10294
10294
  case OpKind.RepeaterCreate:
10295
- op.track = transformExpressionsInExpression(op.track, transform, flags);
10295
+ if (op.trackByOps === null) {
10296
+ op.track = transformExpressionsInExpression(op.track, transform, flags);
10297
+ }
10298
+ else {
10299
+ for (const innerOp of op.trackByOps) {
10300
+ transformExpressionsInOp(innerOp, transform, flags | VisitorContextFlag.InChildOperation);
10301
+ }
10302
+ }
10296
10303
  if (op.trackByFn !== null) {
10297
10304
  op.trackByFn = transformExpressionsInExpression(op.trackByFn, transform, flags);
10298
10305
  }
@@ -10825,6 +10832,7 @@ function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, em
10825
10832
  emptyView,
10826
10833
  track,
10827
10834
  trackByFn: null,
10835
+ trackByOps: null,
10828
10836
  tag,
10829
10837
  emptyTag,
10830
10838
  emptyAttributes: null,
@@ -11325,6 +11333,11 @@ class CompilationUnit {
11325
11333
  yield listenerOp;
11326
11334
  }
11327
11335
  }
11336
+ else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
11337
+ for (const trackOp of op.trackByOps) {
11338
+ yield trackOp;
11339
+ }
11340
+ }
11328
11341
  }
11329
11342
  for (const op of this.update) {
11330
11343
  yield op;
@@ -13057,6 +13070,9 @@ function recursivelyProcessView(view, parentScope) {
13057
13070
  if (op.emptyView) {
13058
13071
  recursivelyProcessView(view.job.views.get(op.emptyView), scope);
13059
13072
  }
13073
+ if (op.trackByOps !== null) {
13074
+ op.trackByOps.prepend(generateVariablesInScopeForView(view, scope, false));
13075
+ }
13060
13076
  break;
13061
13077
  case OpKind.Listener:
13062
13078
  case OpKind.TwoWayListener:
@@ -23319,7 +23335,7 @@ function reifyCreateOperations(unit, ops) {
23319
23335
  emptyDecls = emptyView.decls;
23320
23336
  emptyVars = emptyView.vars;
23321
23337
  }
23322
- 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));
23338
+ 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));
23323
23339
  break;
23324
23340
  case OpKind.SourceLocation:
23325
23341
  const locationsLiteral = literalArr(op.locations.map(({ targetSlot, offset, line, column }) => {
@@ -23500,6 +23516,8 @@ function reifyIrExpression(expr) {
23500
23516
  return readContextLet(expr.targetSlot.slot);
23501
23517
  case ExpressionKind.StoreLet:
23502
23518
  return storeLet(expr.value, expr.sourceSpan);
23519
+ case ExpressionKind.TrackContext:
23520
+ return variable('this');
23503
23521
  default:
23504
23522
  throw new Error(`AssertionError: Unsupported reification of ir.Expression kind: ${ExpressionKind[expr.kind]}`);
23505
23523
  }
@@ -23528,6 +23546,42 @@ function reifyListenerHandler(unit, name, handlerOps, consumesDollarEvent) {
23528
23546
  }
23529
23547
  return fn(params, handlerStmts, undefined, undefined, name);
23530
23548
  }
23549
+ /** Reifies the tracking expression of a `RepeaterCreateOp`. */
23550
+ function reifyTrackBy(unit, op) {
23551
+ // If the tracking function was created already, there's nothing left to do.
23552
+ if (op.trackByFn !== null) {
23553
+ return op.trackByFn;
23554
+ }
23555
+ const params = [new FnParam('$index'), new FnParam('$item')];
23556
+ let fn$1;
23557
+ if (op.trackByOps === null) {
23558
+ // If there are no additional ops related to the tracking function, we just need
23559
+ // to turn it into a function that returns the result of the expression.
23560
+ fn$1 = op.usesComponentInstance
23561
+ ? fn(params, [new ReturnStatement(op.track)])
23562
+ : arrowFn(params, op.track);
23563
+ }
23564
+ else {
23565
+ // Otherwise first we need to reify the track-related ops.
23566
+ reifyUpdateOperations(unit, op.trackByOps);
23567
+ const statements = [];
23568
+ for (const trackOp of op.trackByOps) {
23569
+ if (trackOp.kind !== OpKind.Statement) {
23570
+ throw new Error(`AssertionError: expected reified statements, but found op ${OpKind[trackOp.kind]}`);
23571
+ }
23572
+ statements.push(trackOp.statement);
23573
+ }
23574
+ // Afterwards we can create the function from those ops.
23575
+ fn$1 =
23576
+ op.usesComponentInstance ||
23577
+ statements.length !== 1 ||
23578
+ !(statements[0] instanceof ReturnStatement)
23579
+ ? fn(params, statements)
23580
+ : arrowFn(params, statements[0].value);
23581
+ }
23582
+ op.trackByFn = unit.job.pool.getSharedFunctionReference(fn$1, '_forTrack');
23583
+ return op.trackByFn;
23584
+ }
23531
23585
 
23532
23586
  /**
23533
23587
  * Binding with no content can be safely deleted.
@@ -23626,6 +23680,11 @@ function processLexicalScope$1(view, ops) {
23626
23680
  case OpKind.TwoWayListener:
23627
23681
  processLexicalScope$1(view, op.handlerOps);
23628
23682
  break;
23683
+ case OpKind.RepeaterCreate:
23684
+ if (op.trackByOps !== null) {
23685
+ processLexicalScope$1(view, op.trackByOps);
23686
+ }
23687
+ break;
23629
23688
  }
23630
23689
  }
23631
23690
  if (view === view.job.root) {
@@ -24058,6 +24117,11 @@ function processLexicalScope(unit, ops, savedView) {
24058
24117
  // lexical scope.
24059
24118
  processLexicalScope(unit, op.handlerOps, savedView);
24060
24119
  break;
24120
+ case OpKind.RepeaterCreate:
24121
+ if (op.trackByOps !== null) {
24122
+ processLexicalScope(unit, op.trackByOps, savedView);
24123
+ }
24124
+ break;
24061
24125
  }
24062
24126
  }
24063
24127
  // Next, use the `scope` mapping to match `ir.LexicalReadExpr` with defined names in the lexical
@@ -24458,6 +24522,9 @@ function generateTemporaries(ops) {
24458
24522
  if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
24459
24523
  op.handlerOps.prepend(generateTemporaries(op.handlerOps));
24460
24524
  }
24525
+ else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
24526
+ op.trackByOps.prepend(generateTemporaries(op.trackByOps));
24527
+ }
24461
24528
  }
24462
24529
  return generatedStatements;
24463
24530
  }
@@ -24472,49 +24539,6 @@ function assignName(names, expr) {
24472
24539
  expr.name = name;
24473
24540
  }
24474
24541
 
24475
- /**
24476
- * Generate track functions that need to be extracted to the constant pool. This entails wrapping
24477
- * them in an arrow (or traditional) function, replacing context reads with `this.`, and storing
24478
- * them in the constant pool.
24479
- *
24480
- * Note that, if a track function was previously optimized, it will not need to be extracted, and
24481
- * this phase is a no-op.
24482
- */
24483
- function generateTrackFns(job) {
24484
- for (const unit of job.units) {
24485
- for (const op of unit.create) {
24486
- if (op.kind !== OpKind.RepeaterCreate) {
24487
- continue;
24488
- }
24489
- if (op.trackByFn !== null) {
24490
- // The final track function was already set, probably because it was optimized.
24491
- continue;
24492
- }
24493
- // Find all component context reads.
24494
- let usesComponentContext = false;
24495
- op.track = transformExpressionsInExpression(op.track, (expr) => {
24496
- if (expr instanceof PipeBindingExpr || expr instanceof PipeBindingVariadicExpr) {
24497
- throw new Error(`Illegal State: Pipes are not allowed in this context`);
24498
- }
24499
- if (expr instanceof TrackContextExpr) {
24500
- usesComponentContext = true;
24501
- return variable('this');
24502
- }
24503
- return expr;
24504
- }, VisitorContextFlag.None);
24505
- let fn;
24506
- const fnParams = [new FnParam('$index'), new FnParam('$item')];
24507
- if (usesComponentContext) {
24508
- fn = new FunctionExpr(fnParams, [new ReturnStatement(op.track)]);
24509
- }
24510
- else {
24511
- fn = arrowFn(fnParams, op.track);
24512
- }
24513
- op.trackByFn = job.pool.getSharedFunctionReference(fn, '_forTrack');
24514
- }
24515
- }
24516
- }
24517
-
24518
24542
  /**
24519
24543
  * `track` functions in `for` repeaters can sometimes be "optimized," i.e. transformed into inline
24520
24544
  * expressions, in lieu of an external function call. For example, tracking by `$index` can be be
@@ -24561,12 +24585,20 @@ function optimizeTrackFns(job) {
24561
24585
  // Replace context reads with a special IR expression, since context reads in a track
24562
24586
  // function are emitted specially.
24563
24587
  op.track = transformExpressionsInExpression(op.track, (expr) => {
24564
- if (expr instanceof ContextExpr) {
24588
+ if (expr instanceof PipeBindingExpr || expr instanceof PipeBindingVariadicExpr) {
24589
+ throw new Error(`Illegal State: Pipes are not allowed in this context`);
24590
+ }
24591
+ else if (expr instanceof ContextExpr) {
24565
24592
  op.usesComponentInstance = true;
24566
24593
  return new TrackContextExpr(expr.view);
24567
24594
  }
24568
24595
  return expr;
24569
24596
  }, VisitorContextFlag.None);
24597
+ // Also create an OpList for the tracking expression since it may need
24598
+ // additional ops when generating the final code (e.g. temporary variables).
24599
+ const trackOpList = new OpList();
24600
+ trackOpList.push(createStatementOp(new ReturnStatement(op.track, op.track.sourceSpan)));
24601
+ op.trackByOps = trackOpList;
24570
24602
  }
24571
24603
  }
24572
24604
  }
@@ -24791,6 +24823,9 @@ function optimizeVariables(job) {
24791
24823
  if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
24792
24824
  inlineAlwaysInlineVariables(op.handlerOps);
24793
24825
  }
24826
+ else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
24827
+ inlineAlwaysInlineVariables(op.trackByOps);
24828
+ }
24794
24829
  }
24795
24830
  optimizeVariablesInOpList(unit.create, job.compatibility);
24796
24831
  optimizeVariablesInOpList(unit.update, job.compatibility);
@@ -24798,6 +24833,9 @@ function optimizeVariables(job) {
24798
24833
  if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
24799
24834
  optimizeVariablesInOpList(op.handlerOps, job.compatibility);
24800
24835
  }
24836
+ else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
24837
+ optimizeVariablesInOpList(op.trackByOps, job.compatibility);
24838
+ }
24801
24839
  }
24802
24840
  }
24803
24841
  }
@@ -25378,7 +25416,6 @@ const phases = [
25378
25416
  { kind: CompilationJobKind.Tmpl, fn: resolveI18nElementPlaceholders },
25379
25417
  { kind: CompilationJobKind.Tmpl, fn: resolveI18nExpressionPlaceholders },
25380
25418
  { kind: CompilationJobKind.Tmpl, fn: extractI18nMessages },
25381
- { kind: CompilationJobKind.Tmpl, fn: generateTrackFns },
25382
25419
  { kind: CompilationJobKind.Tmpl, fn: collectI18nConsts },
25383
25420
  { kind: CompilationJobKind.Tmpl, fn: collectConstExpressions },
25384
25421
  { kind: CompilationJobKind.Both, fn: collectElementConsts },
@@ -31008,7 +31045,7 @@ function publishFacade(global) {
31008
31045
  * @description
31009
31046
  * Entry point for all public APIs of the compiler package.
31010
31047
  */
31011
- const VERSION = new Version('19.2.0-next.2');
31048
+ const VERSION = new Version('19.2.0-next.3');
31012
31049
 
31013
31050
  class CompilerConfig {
31014
31051
  defaultEncapsulation;
@@ -32759,29 +32796,32 @@ function compileClassDebugInfo(debugInfo) {
32759
32796
  * @param meta HMR metadata extracted from the class.
32760
32797
  */
32761
32798
  function compileHmrInitializer(meta) {
32762
- const id = encodeURIComponent(`${meta.filePath}@${meta.className}`);
32763
- const urlPartial = `./@ng/component?c=${id}&t=`;
32764
32799
  const moduleName = 'm';
32765
32800
  const dataName = 'd';
32766
32801
  const timestampName = 't';
32802
+ const idName = 'id';
32767
32803
  const importCallbackName = `${meta.className}_HmrLoad`;
32768
32804
  const namespaces = meta.namespaceDependencies.map((dep) => {
32769
32805
  return new ExternalExpr({ moduleName: dep.moduleName, name: null });
32770
32806
  });
32771
32807
  // m.default
32772
32808
  const defaultRead = variable(moduleName).prop('default');
32773
- // ɵɵreplaceMetadata(Comp, m.default, [...namespaces], [...locals]);
32809
+ // ɵɵreplaceMetadata(Comp, m.default, [...namespaces], [...locals], import.meta, id);
32774
32810
  const replaceCall = importExpr(Identifiers.replaceMetadata)
32775
32811
  .callFn([
32776
32812
  meta.type,
32777
32813
  defaultRead,
32778
32814
  literalArr(namespaces),
32779
32815
  literalArr(meta.localDependencies.map((l) => l.runtimeRepresentation)),
32816
+ variable('import').prop('meta'),
32817
+ variable(idName),
32780
32818
  ]);
32781
32819
  // (m) => m.default && ɵɵreplaceMetadata(...)
32782
32820
  const replaceCallback = arrowFn([new FnParam(moduleName)], defaultRead.and(replaceCall));
32783
- // '<urlPartial>' + encodeURIComponent(t)
32784
- const urlValue = literal(urlPartial)
32821
+ // '<url>?c=' + id + '&t=' + encodeURIComponent(t)
32822
+ const urlValue = literal(`./@ng/component?c=`)
32823
+ .plus(variable(idName))
32824
+ .plus(literal('&t='))
32785
32825
  .plus(variable('encodeURIComponent').callFn([variable(timestampName)]));
32786
32826
  // import.meta.url
32787
32827
  const urlBase = variable('import').prop('meta').prop('url');
@@ -32799,10 +32839,10 @@ function compileHmrInitializer(meta) {
32799
32839
  .callFn([replaceCallback])
32800
32840
  .toStmt(),
32801
32841
  ], null, StmtModifier.Final);
32802
- // (d) => d.id === <id> && Cmp_HmrLoad(d.timestamp)
32842
+ // (d) => d.id === id && Cmp_HmrLoad(d.timestamp)
32803
32843
  const updateCallback = arrowFn([new FnParam(dataName)], variable(dataName)
32804
32844
  .prop('id')
32805
- .identical(literal(id))
32845
+ .identical(variable(idName))
32806
32846
  .and(variable(importCallbackName).callFn([variable(dataName).prop('timestamp')])));
32807
32847
  // Cmp_HmrLoad(Date.now());
32808
32848
  // Initial call to kick off the loading in order to avoid edge cases with components
@@ -32817,6 +32857,8 @@ function compileHmrInitializer(meta) {
32817
32857
  .prop('on')
32818
32858
  .callFn([literal('angular:component-update'), updateCallback]);
32819
32859
  return arrowFn([], [
32860
+ // const id = <id>;
32861
+ new DeclareVarStmt(idName, literal(encodeURIComponent(`${meta.filePath}@${meta.className}`)), null, StmtModifier.Final),
32820
32862
  // function Cmp_HmrLoad() {...}.
32821
32863
  importCallback,
32822
32864
  // ngDevMode && Cmp_HmrLoad(Date.now());
@@ -32871,7 +32913,7 @@ const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
32871
32913
  function compileDeclareClassMetadata(metadata) {
32872
32914
  const definitionMap = new DefinitionMap();
32873
32915
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
32874
- definitionMap.set('version', literal('19.2.0-next.2'));
32916
+ definitionMap.set('version', literal('19.2.0-next.3'));
32875
32917
  definitionMap.set('ngImport', importExpr(Identifiers.core));
32876
32918
  definitionMap.set('type', metadata.type);
32877
32919
  definitionMap.set('decorators', metadata.decorators);
@@ -32889,7 +32931,7 @@ function compileComponentDeclareClassMetadata(metadata, dependencies) {
32889
32931
  callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? literal(null));
32890
32932
  callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? literal(null));
32891
32933
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
32892
- definitionMap.set('version', literal('19.2.0-next.2'));
32934
+ definitionMap.set('version', literal('19.2.0-next.3'));
32893
32935
  definitionMap.set('ngImport', importExpr(Identifiers.core));
32894
32936
  definitionMap.set('type', metadata.type);
32895
32937
  definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
@@ -32984,7 +33026,7 @@ function createDirectiveDefinitionMap(meta) {
32984
33026
  const definitionMap = new DefinitionMap();
32985
33027
  const minVersion = getMinimumVersionForPartialOutput(meta);
32986
33028
  definitionMap.set('minVersion', literal(minVersion));
32987
- definitionMap.set('version', literal('19.2.0-next.2'));
33029
+ definitionMap.set('version', literal('19.2.0-next.3'));
32988
33030
  // e.g. `type: MyDirective`
32989
33031
  definitionMap.set('type', meta.type.value);
32990
33032
  if (meta.isStandalone !== undefined) {
@@ -33403,7 +33445,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
33403
33445
  function compileDeclareFactoryFunction(meta) {
33404
33446
  const definitionMap = new DefinitionMap();
33405
33447
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
33406
- definitionMap.set('version', literal('19.2.0-next.2'));
33448
+ definitionMap.set('version', literal('19.2.0-next.3'));
33407
33449
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33408
33450
  definitionMap.set('type', meta.type.value);
33409
33451
  definitionMap.set('deps', compileDependencies(meta.deps));
@@ -33438,7 +33480,7 @@ function compileDeclareInjectableFromMetadata(meta) {
33438
33480
  function createInjectableDefinitionMap(meta) {
33439
33481
  const definitionMap = new DefinitionMap();
33440
33482
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
33441
- definitionMap.set('version', literal('19.2.0-next.2'));
33483
+ definitionMap.set('version', literal('19.2.0-next.3'));
33442
33484
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33443
33485
  definitionMap.set('type', meta.type.value);
33444
33486
  // Only generate providedIn property if it has a non-null value
@@ -33489,7 +33531,7 @@ function compileDeclareInjectorFromMetadata(meta) {
33489
33531
  function createInjectorDefinitionMap(meta) {
33490
33532
  const definitionMap = new DefinitionMap();
33491
33533
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
33492
- definitionMap.set('version', literal('19.2.0-next.2'));
33534
+ definitionMap.set('version', literal('19.2.0-next.3'));
33493
33535
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33494
33536
  definitionMap.set('type', meta.type.value);
33495
33537
  definitionMap.set('providers', meta.providers);
@@ -33522,7 +33564,7 @@ function createNgModuleDefinitionMap(meta) {
33522
33564
  throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
33523
33565
  }
33524
33566
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
33525
- definitionMap.set('version', literal('19.2.0-next.2'));
33567
+ definitionMap.set('version', literal('19.2.0-next.3'));
33526
33568
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33527
33569
  definitionMap.set('type', meta.type.value);
33528
33570
  // We only generate the keys in the metadata if the arrays contain values.
@@ -33573,7 +33615,7 @@ function compileDeclarePipeFromMetadata(meta) {
33573
33615
  function createPipeDefinitionMap(meta) {
33574
33616
  const definitionMap = new DefinitionMap();
33575
33617
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
33576
- definitionMap.set('version', literal('19.2.0-next.2'));
33618
+ definitionMap.set('version', literal('19.2.0-next.3'));
33577
33619
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33578
33620
  // e.g. `type: MyPipe`
33579
33621
  definitionMap.set('type', meta.type.value);