@angular/compiler 18.0.0-next.4 → 18.0.0-next.5

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 v18.0.0-next.4
2
+ * @license Angular v18.0.0-next.5
3
3
  * (c) 2010-2024 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -8545,11 +8545,10 @@ function createAdvanceOp(delta, sourceSpan) {
8545
8545
  /**
8546
8546
  * Create a conditional op, which will display an embedded view according to a condtion.
8547
8547
  */
8548
- function createConditionalOp(target, targetSlot, test, conditions, sourceSpan) {
8548
+ function createConditionalOp(target, test, conditions, sourceSpan) {
8549
8549
  return {
8550
8550
  kind: OpKind.Conditional,
8551
8551
  target,
8552
- targetSlot,
8553
8552
  test,
8554
8553
  conditions,
8555
8554
  processed: null,
@@ -20789,21 +20788,7 @@ function pipeBindV(slot, varOffset, args) {
20789
20788
  ]);
20790
20789
  }
20791
20790
  function textInterpolate(strings, expressions, sourceSpan) {
20792
- if (strings.length < 1 || expressions.length !== strings.length - 1) {
20793
- throw new Error(`AssertionError: expected specific shape of args for strings/expressions in interpolation`);
20794
- }
20795
- const interpolationArgs = [];
20796
- if (expressions.length === 1 && strings[0] === '' && strings[1] === '') {
20797
- interpolationArgs.push(expressions[0]);
20798
- }
20799
- else {
20800
- let idx;
20801
- for (idx = 0; idx < expressions.length; idx++) {
20802
- interpolationArgs.push(literal(strings[idx]), expressions[idx]);
20803
- }
20804
- // idx points at the last string.
20805
- interpolationArgs.push(literal(strings[idx]));
20806
- }
20791
+ const interpolationArgs = collateInterpolationArgs(strings, expressions);
20807
20792
  return callVariadicInstruction(TEXT_INTERPOLATE_CONFIG, [], interpolationArgs, [], sourceSpan);
20808
20793
  }
20809
20794
  function i18nExp(expr, sourceSpan) {
@@ -20885,8 +20870,8 @@ function call(instruction, args, sourceSpan) {
20885
20870
  const expr = importExpr(instruction).callFn(args, sourceSpan);
20886
20871
  return createStatementOp(new ExpressionStatement(expr, sourceSpan));
20887
20872
  }
20888
- function conditional(slot, condition, contextValue, sourceSpan) {
20889
- const args = [literal(slot), condition];
20873
+ function conditional(condition, contextValue, sourceSpan) {
20874
+ const args = [condition];
20890
20875
  if (contextValue !== null) {
20891
20876
  args.push(contextValue);
20892
20877
  }
@@ -21380,10 +21365,7 @@ function reifyUpdateOperations(_unit, ops) {
21380
21365
  if (op.processed === null) {
21381
21366
  throw new Error(`Conditional test was not set.`);
21382
21367
  }
21383
- if (op.targetSlot.slot === null) {
21384
- throw new Error(`Conditional slot was not set.`);
21385
- }
21386
- OpList.replace(op, conditional(op.targetSlot.slot, op.processed, op.contextValue, op.sourceSpan));
21368
+ OpList.replace(op, conditional(op.processed, op.contextValue, op.sourceSpan));
21387
21369
  break;
21388
21370
  case OpKind.Repeater:
21389
21371
  OpList.replace(op, repeater(op.collection, op.sourceSpan));
@@ -22160,72 +22142,27 @@ function transformTwoWayBindingSet(job) {
22160
22142
  for (const op of unit.create) {
22161
22143
  if (op.kind === OpKind.TwoWayListener) {
22162
22144
  transformExpressionsInOp(op, (expr) => {
22163
- if (expr instanceof TwoWayBindingSetExpr) {
22164
- return wrapAction(expr.target, expr.value);
22145
+ if (!(expr instanceof TwoWayBindingSetExpr)) {
22146
+ return expr;
22165
22147
  }
22166
- return expr;
22148
+ const { target, value } = expr;
22149
+ if (target instanceof ReadPropExpr || target instanceof ReadKeyExpr) {
22150
+ return twoWayBindingSet(target, value).or(target.set(value));
22151
+ }
22152
+ // ASSUMPTION: here we're assuming that `ReadVariableExpr` will be a reference
22153
+ // to a local template variable. This appears to be the case at the time of writing.
22154
+ // If the expression is targeting a variable read, we only emit the `twoWayBindingSet`
22155
+ // since the fallback would be attempting to write into a constant. Invalid usages will be
22156
+ // flagged during template type checking.
22157
+ if (target instanceof ReadVariableExpr) {
22158
+ return twoWayBindingSet(target, value);
22159
+ }
22160
+ throw new Error(`Unsupported expression in two-way action binding.`);
22167
22161
  }, VisitorContextFlag.InChildOperation);
22168
22162
  }
22169
22163
  }
22170
22164
  }
22171
22165
  }
22172
- function wrapSetOperation(target, value) {
22173
- // ASSUMPTION: here we're assuming that `ReadVariableExpr` will be a reference
22174
- // to a local template variable. This appears to be the case at the time of writing.
22175
- // If the expression is targeting a variable read, we only emit the `twoWayBindingSet` since
22176
- // the fallback would be attempting to write into a constant. Invalid usages will be flagged
22177
- // during template type checking.
22178
- if (target instanceof ReadVariableExpr) {
22179
- return twoWayBindingSet(target, value);
22180
- }
22181
- return twoWayBindingSet(target, value).or(target.set(value));
22182
- }
22183
- function isReadExpression(value) {
22184
- return value instanceof ReadPropExpr || value instanceof ReadKeyExpr ||
22185
- value instanceof ReadVariableExpr;
22186
- }
22187
- function wrapAction(target, value) {
22188
- // The only officially supported expressions inside of a two-way binding are read expressions.
22189
- if (isReadExpression(target)) {
22190
- return wrapSetOperation(target, value);
22191
- }
22192
- // However, historically the expression parser was handling two-way events by appending `=$event`
22193
- // to the raw string before attempting to parse it. This has led to bugs over the years (see
22194
- // #37809) and to unintentionally supporting unassignable events in the two-way binding. The
22195
- // logic below aims to emulate the old behavior while still supporting the new output format
22196
- // which uses `twoWayBindingSet`. Note that the generated code doesn't necessarily make sense
22197
- // based on what the user wrote, for example the event binding for `[(value)]="a ? b : c"`
22198
- // would produce `ctx.a ? ctx.b : ctx.c = $event`. We aim to reproduce what the parser used
22199
- // to generate before #54154.
22200
- if (target instanceof BinaryOperatorExpr && isReadExpression(target.rhs)) {
22201
- // `a && b` -> `ctx.a && twoWayBindingSet(ctx.b, $event) || (ctx.b = $event)`
22202
- return new BinaryOperatorExpr(target.operator, target.lhs, wrapSetOperation(target.rhs, value));
22203
- }
22204
- // Note: this also supports nullish coalescing expressions which
22205
- // would've been downleveled to ternary expressions by this point.
22206
- if (target instanceof ConditionalExpr && isReadExpression(target.falseCase)) {
22207
- // `a ? b : c` -> `ctx.a ? ctx.b : twoWayBindingSet(ctx.c, $event) || (ctx.c = $event)`
22208
- return new ConditionalExpr(target.condition, target.trueCase, wrapSetOperation(target.falseCase, value));
22209
- }
22210
- // `!!a` -> `twoWayBindingSet(ctx.a, $event) || (ctx.a = $event)`
22211
- // Note: previously we'd actually produce `!!(ctx.a = $event)`, but the wrapping
22212
- // node doesn't affect the result so we don't need to carry it over.
22213
- if (target instanceof NotExpr) {
22214
- let expr = target.condition;
22215
- while (true) {
22216
- if (expr instanceof NotExpr) {
22217
- expr = expr.condition;
22218
- }
22219
- else {
22220
- if (isReadExpression(expr)) {
22221
- return wrapSetOperation(expr, value);
22222
- }
22223
- break;
22224
- }
22225
- }
22226
- }
22227
- throw new Error(`Unsupported expression in two-way action binding.`);
22228
- }
22229
22166
 
22230
22167
  /**
22231
22168
  * When inside of a listener, we may need access to one or more enclosing views. Therefore, each
@@ -23610,7 +23547,6 @@ function ingestBoundText(unit, text, icuPlaceholder) {
23610
23547
  */
23611
23548
  function ingestIfBlock(unit, ifBlock) {
23612
23549
  let firstXref = null;
23613
- let firstSlotHandle = null;
23614
23550
  let conditions = [];
23615
23551
  for (let i = 0; i < ifBlock.branches.length; i++) {
23616
23552
  const ifCase = ifBlock.branches[i];
@@ -23630,15 +23566,13 @@ function ingestIfBlock(unit, ifBlock) {
23630
23566
  unit.create.push(templateOp);
23631
23567
  if (firstXref === null) {
23632
23568
  firstXref = cView.xref;
23633
- firstSlotHandle = templateOp.handle;
23634
23569
  }
23635
23570
  const caseExpr = ifCase.expression ? convertAst(ifCase.expression, unit.job, null) : null;
23636
23571
  const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr, templateOp.xref, templateOp.handle, ifCase.expressionAlias);
23637
23572
  conditions.push(conditionalCaseExpr);
23638
23573
  ingestNodes(cView, ifCase.children);
23639
23574
  }
23640
- const conditional = createConditionalOp(firstXref, firstSlotHandle, null, conditions, ifBlock.sourceSpan);
23641
- unit.update.push(conditional);
23575
+ unit.update.push(createConditionalOp(firstXref, null, conditions, ifBlock.sourceSpan));
23642
23576
  }
23643
23577
  /**
23644
23578
  * Ingest an `@switch` block into the given `ViewCompilation`.
@@ -23649,7 +23583,6 @@ function ingestSwitchBlock(unit, switchBlock) {
23649
23583
  return;
23650
23584
  }
23651
23585
  let firstXref = null;
23652
- let firstSlotHandle = null;
23653
23586
  let conditions = [];
23654
23587
  for (const switchCase of switchBlock.cases) {
23655
23588
  const cView = unit.job.allocateView(unit.xref);
@@ -23665,7 +23598,6 @@ function ingestSwitchBlock(unit, switchBlock) {
23665
23598
  unit.create.push(templateOp);
23666
23599
  if (firstXref === null) {
23667
23600
  firstXref = cView.xref;
23668
- firstSlotHandle = templateOp.handle;
23669
23601
  }
23670
23602
  const caseExpr = switchCase.expression ?
23671
23603
  convertAst(switchCase.expression, unit.job, switchBlock.startSourceSpan) :
@@ -23674,8 +23606,7 @@ function ingestSwitchBlock(unit, switchBlock) {
23674
23606
  conditions.push(conditionalCaseExpr);
23675
23607
  ingestNodes(cView, switchCase.children);
23676
23608
  }
23677
- const conditional = createConditionalOp(firstXref, firstSlotHandle, convertAst(switchBlock.expression, unit.job, null), conditions, switchBlock.sourceSpan);
23678
- unit.update.push(conditional);
23609
+ unit.update.push(createConditionalOp(firstXref, convertAst(switchBlock.expression, unit.job, null), conditions, switchBlock.sourceSpan));
23679
23610
  }
23680
23611
  function ingestDeferView(unit, suffix, i18nMeta, children, sourceSpan) {
23681
23612
  if (i18nMeta !== undefined && !(i18nMeta instanceof BlockPlaceholder)) {
@@ -24672,11 +24603,12 @@ const ANIMATE_PROP_PREFIX = 'animate-';
24672
24603
  * Parses bindings in templates and in the directive host area.
24673
24604
  */
24674
24605
  class BindingParser {
24675
- constructor(_exprParser, _interpolationConfig, _schemaRegistry, errors) {
24606
+ constructor(_exprParser, _interpolationConfig, _schemaRegistry, errors, _allowInvalidAssignmentEvents = false) {
24676
24607
  this._exprParser = _exprParser;
24677
24608
  this._interpolationConfig = _interpolationConfig;
24678
24609
  this._schemaRegistry = _schemaRegistry;
24679
24610
  this.errors = errors;
24611
+ this._allowInvalidAssignmentEvents = _allowInvalidAssignmentEvents;
24680
24612
  }
24681
24613
  get interpolationConfig() {
24682
24614
  return this._interpolationConfig;
@@ -25056,6 +24988,11 @@ class BindingParser {
25056
24988
  if (ast instanceof PropertyRead || ast instanceof KeyedRead) {
25057
24989
  return true;
25058
24990
  }
24991
+ // TODO(crisbeto): this logic is only here to support the automated migration away
24992
+ // from invalid bindings. It should be removed once the migration is deleted.
24993
+ if (!this._allowInvalidAssignmentEvents) {
24994
+ return false;
24995
+ }
25059
24996
  if (ast instanceof Binary) {
25060
24997
  return (ast.operation === '&&' || ast.operation === '||' || ast.operation === '??') &&
25061
24998
  (ast.right instanceof PropertyRead || ast.right instanceof KeyedRead);
@@ -26580,8 +26517,8 @@ const LEADING_TRIVIA_CHARS = [' ', '\n', '\r', '\t'];
26580
26517
  * @param options options to modify how the template is parsed
26581
26518
  */
26582
26519
  function parseTemplate(template, templateUrl, options = {}) {
26583
- const { interpolationConfig, preserveWhitespaces, enableI18nLegacyMessageIdFormat } = options;
26584
- const bindingParser = makeBindingParser(interpolationConfig);
26520
+ const { interpolationConfig, preserveWhitespaces, enableI18nLegacyMessageIdFormat, allowInvalidAssignmentEvents } = options;
26521
+ const bindingParser = makeBindingParser(interpolationConfig, allowInvalidAssignmentEvents);
26585
26522
  const htmlParser = new HtmlParser();
26586
26523
  const parseResult = htmlParser.parse(template, templateUrl, {
26587
26524
  leadingTriviaChars: LEADING_TRIVIA_CHARS,
@@ -26659,8 +26596,8 @@ const elementRegistry = new DomElementSchemaRegistry();
26659
26596
  /**
26660
26597
  * Construct a `BindingParser` with a default configuration.
26661
26598
  */
26662
- function makeBindingParser(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
26663
- return new BindingParser(new Parser$1(new Lexer()), interpolationConfig, elementRegistry, []);
26599
+ function makeBindingParser(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG, allowInvalidAssignmentEvents = false) {
26600
+ return new BindingParser(new Parser$1(new Lexer()), interpolationConfig, elementRegistry, [], allowInvalidAssignmentEvents);
26664
26601
  }
26665
26602
 
26666
26603
  const COMPONENT_VARIABLE = '%COMP%';
@@ -28620,7 +28557,7 @@ function publishFacade(global) {
28620
28557
  * @description
28621
28558
  * Entry point for all public APIs of the compiler package.
28622
28559
  */
28623
- const VERSION = new Version('18.0.0-next.4');
28560
+ const VERSION = new Version('18.0.0-next.5');
28624
28561
 
28625
28562
  class CompilerConfig {
28626
28563
  constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, preserveWhitespaces, strictInjectionParameters } = {}) {
@@ -30205,7 +30142,7 @@ const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
30205
30142
  function compileDeclareClassMetadata(metadata) {
30206
30143
  const definitionMap = new DefinitionMap();
30207
30144
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
30208
- definitionMap.set('version', literal('18.0.0-next.4'));
30145
+ definitionMap.set('version', literal('18.0.0-next.5'));
30209
30146
  definitionMap.set('ngImport', importExpr(Identifiers.core));
30210
30147
  definitionMap.set('type', metadata.type);
30211
30148
  definitionMap.set('decorators', metadata.decorators);
@@ -30223,7 +30160,7 @@ function compileComponentDeclareClassMetadata(metadata, dependencies) {
30223
30160
  callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? literal(null));
30224
30161
  callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? literal(null));
30225
30162
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
30226
- definitionMap.set('version', literal('18.0.0-next.4'));
30163
+ definitionMap.set('version', literal('18.0.0-next.5'));
30227
30164
  definitionMap.set('ngImport', importExpr(Identifiers.core));
30228
30165
  definitionMap.set('type', metadata.type);
30229
30166
  definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
@@ -30318,7 +30255,7 @@ function createDirectiveDefinitionMap(meta) {
30318
30255
  const definitionMap = new DefinitionMap();
30319
30256
  const minVersion = getMinimumVersionForPartialOutput(meta);
30320
30257
  definitionMap.set('minVersion', literal(minVersion));
30321
- definitionMap.set('version', literal('18.0.0-next.4'));
30258
+ definitionMap.set('version', literal('18.0.0-next.5'));
30322
30259
  // e.g. `type: MyDirective`
30323
30260
  definitionMap.set('type', meta.type.value);
30324
30261
  if (meta.isStandalone) {
@@ -30733,7 +30670,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
30733
30670
  function compileDeclareFactoryFunction(meta) {
30734
30671
  const definitionMap = new DefinitionMap();
30735
30672
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
30736
- definitionMap.set('version', literal('18.0.0-next.4'));
30673
+ definitionMap.set('version', literal('18.0.0-next.5'));
30737
30674
  definitionMap.set('ngImport', importExpr(Identifiers.core));
30738
30675
  definitionMap.set('type', meta.type.value);
30739
30676
  definitionMap.set('deps', compileDependencies(meta.deps));
@@ -30768,7 +30705,7 @@ function compileDeclareInjectableFromMetadata(meta) {
30768
30705
  function createInjectableDefinitionMap(meta) {
30769
30706
  const definitionMap = new DefinitionMap();
30770
30707
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
30771
- definitionMap.set('version', literal('18.0.0-next.4'));
30708
+ definitionMap.set('version', literal('18.0.0-next.5'));
30772
30709
  definitionMap.set('ngImport', importExpr(Identifiers.core));
30773
30710
  definitionMap.set('type', meta.type.value);
30774
30711
  // Only generate providedIn property if it has a non-null value
@@ -30819,7 +30756,7 @@ function compileDeclareInjectorFromMetadata(meta) {
30819
30756
  function createInjectorDefinitionMap(meta) {
30820
30757
  const definitionMap = new DefinitionMap();
30821
30758
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
30822
- definitionMap.set('version', literal('18.0.0-next.4'));
30759
+ definitionMap.set('version', literal('18.0.0-next.5'));
30823
30760
  definitionMap.set('ngImport', importExpr(Identifiers.core));
30824
30761
  definitionMap.set('type', meta.type.value);
30825
30762
  definitionMap.set('providers', meta.providers);
@@ -30852,7 +30789,7 @@ function createNgModuleDefinitionMap(meta) {
30852
30789
  throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
30853
30790
  }
30854
30791
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
30855
- definitionMap.set('version', literal('18.0.0-next.4'));
30792
+ definitionMap.set('version', literal('18.0.0-next.5'));
30856
30793
  definitionMap.set('ngImport', importExpr(Identifiers.core));
30857
30794
  definitionMap.set('type', meta.type.value);
30858
30795
  // We only generate the keys in the metadata if the arrays contain values.
@@ -30903,7 +30840,7 @@ function compileDeclarePipeFromMetadata(meta) {
30903
30840
  function createPipeDefinitionMap(meta) {
30904
30841
  const definitionMap = new DefinitionMap();
30905
30842
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
30906
- definitionMap.set('version', literal('18.0.0-next.4'));
30843
+ definitionMap.set('version', literal('18.0.0-next.5'));
30907
30844
  definitionMap.set('ngImport', importExpr(Identifiers.core));
30908
30845
  // e.g. `type: MyPipe`
30909
30846
  definitionMap.set('type', meta.type.value);