@angular/compiler 17.0.0-next.0 → 17.0.0-next.1

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 v17.0.0-next.0
2
+ * @license Angular v17.0.0-next.1
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -2628,6 +2628,7 @@ class Identifiers {
2628
2628
  static { this.deferPrefetchOnHover = { name: 'ɵɵdeferPrefetchOnHover', moduleName: CORE }; }
2629
2629
  static { this.deferPrefetchOnInteraction = { name: 'ɵɵdeferPrefetchOnInteraction', moduleName: CORE }; }
2630
2630
  static { this.deferPrefetchOnViewport = { name: 'ɵɵdeferPrefetchOnViewport', moduleName: CORE }; }
2631
+ static { this.conditional = { name: 'ɵɵconditional', moduleName: CORE }; }
2631
2632
  static { this.text = { name: 'ɵɵtext', moduleName: CORE }; }
2632
2633
  static { this.enableBindings = { name: 'ɵɵenableBindings', moduleName: CORE }; }
2633
2634
  static { this.disableBindings = { name: 'ɵɵdisableBindings', moduleName: CORE }; }
@@ -4053,12 +4054,11 @@ class SwitchBlockCase {
4053
4054
  }
4054
4055
  }
4055
4056
  class ForLoopBlock {
4056
- constructor(itemName, expression,
4057
- // TODO(crisbeto): figure out if trackBy should be an AST
4058
- trackBy, children, empty, sourceSpan, startSourceSpan, endSourceSpan) {
4057
+ constructor(itemName, expression, trackBy, contextVariables, children, empty, sourceSpan, startSourceSpan, endSourceSpan) {
4059
4058
  this.itemName = itemName;
4060
4059
  this.expression = expression;
4061
4060
  this.trackBy = trackBy;
4061
+ this.contextVariables = contextVariables;
4062
4062
  this.children = children;
4063
4063
  this.empty = empty;
4064
4064
  this.sourceSpan = sourceSpan;
@@ -4869,7 +4869,7 @@ function declareI18nVariable(variable) {
4869
4869
  /**
4870
4870
  * Checks whether an object key contains potentially unsafe chars, thus the key should be wrapped in
4871
4871
  * quotes. Note: we do not wrap all keys into quotes, as it may have impact on minification and may
4872
- * bot work in some cases when object keys are mangled by minifier.
4872
+ * not work in some cases when object keys are mangled by a minifier.
4873
4873
  *
4874
4874
  * TODO(FW-1136): this is a temporary solution, we need to come up with a better way of working with
4875
4875
  * inputs that contain potentially unsafe chars.
@@ -4889,6 +4889,8 @@ const IMPLICIT_REFERENCE = '$implicit';
4889
4889
  const NON_BINDABLE_ATTR = 'ngNonBindable';
4890
4890
  /** Name for the variable keeping track of the context returned by `ɵɵrestoreView`. */
4891
4891
  const RESTORED_VIEW_CONTEXT_NAME = 'restoredCtx';
4892
+ /** Special value representing a direct access to a template's context. */
4893
+ const DIRECT_CONTEXT_REFERENCE = '#context';
4892
4894
  /**
4893
4895
  * Maximum length of a single instruction chain. Because our output AST uses recursion, we're
4894
4896
  * limited in how many expressions we can nest before we reach the call stack limit. This
@@ -21470,6 +21472,10 @@ const FOR_LOOP_TRACK_PATTERN = /^track\s+(.*)/;
21470
21472
  const CONDITIONAL_ALIAS_PATTERN = /^as\s+(.*)/;
21471
21473
  /** Pattern used to identify an `else if` block. */
21472
21474
  const ELSE_IF_PATTERN = /^if\s/;
21475
+ /** Pattern used to identify a `let` parameter. */
21476
+ const FOR_LOOP_LET_PATTERN = /^let\s+(.*)/;
21477
+ /** Names of variables that are allowed to be used in the `let` expression of a `for` loop. */
21478
+ const ALLOWED_FOR_LOOP_LET_VARIABLES = new Set(['$index', '$first', '$last', '$even', '$odd', '$count']);
21473
21479
  /** Creates an `if` loop block from an HTML AST node. */
21474
21480
  function createIfBlock(ast, visitor, bindingParser) {
21475
21481
  const errors = validateIfBlock(ast);
@@ -21485,9 +21491,7 @@ function createIfBlock(ast, visitor, bindingParser) {
21485
21491
  branches.push(new IfBlockBranch(null, children, null, block.sourceSpan, block.startSourceSpan));
21486
21492
  continue;
21487
21493
  }
21488
- // Expressions for `{:else if}` blocks start at 2 to skip the `if` from the expression.
21489
- const expressionStart = block.name === 'if' ? 0 : 2;
21490
- const params = parseConditionalBlockParameters(block, errors, bindingParser, expressionStart);
21494
+ const params = parseConditionalBlockParameters(block, errors, bindingParser);
21491
21495
  if (params !== null) {
21492
21496
  branches.push(new IfBlockBranch(params.expression, children, params.expressionAlias, block.sourceSpan, block.startSourceSpan));
21493
21497
  }
@@ -21525,7 +21529,7 @@ function createForLoop(ast, visitor, bindingParser) {
21525
21529
  errors.push(new ParseError(ast.sourceSpan, 'For loop must have a "track" expression'));
21526
21530
  }
21527
21531
  else {
21528
- node = new ForLoopBlock(params.itemName, params.expression, params.trackBy, visitAll(visitor, primaryBlock.children), empty, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
21532
+ node = new ForLoopBlock(params.itemName, params.expression, params.trackBy, params.context, visitAll(visitor, primaryBlock.children), empty, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
21529
21533
  }
21530
21534
  }
21531
21535
  return { node, errors };
@@ -21578,29 +21582,50 @@ function parseForLoopParameters(block, errors, bindingParser) {
21578
21582
  const result = {
21579
21583
  itemName,
21580
21584
  trackBy: null,
21581
- expression: bindingParser.parseBinding(rawExpression, false, expressionParam.sourceSpan,
21582
- // Note: `lastIndexOf` here should be enough to know the start index of the expression,
21583
- // because we know that it'll be the last matching group. Ideally we could use the `d`
21584
- // flag on the regex and get the index from `match.indices`, but it's unclear if we can
21585
- // use it yet since it's a relatively new feature. See:
21586
- // https://github.com/tc39/proposal-regexp-match-indices
21587
- Math.max(0, expressionParam.expression.lastIndexOf(rawExpression)))
21585
+ expression: parseBlockParameterToBinding(expressionParam, bindingParser, rawExpression),
21586
+ context: null,
21588
21587
  };
21589
21588
  for (const param of secondaryParams) {
21589
+ const letMatch = param.expression.match(FOR_LOOP_LET_PATTERN);
21590
+ if (letMatch !== null) {
21591
+ result.context = result.context || {};
21592
+ parseLetParameter(param.sourceSpan, letMatch[1], result.context, errors);
21593
+ continue;
21594
+ }
21590
21595
  const trackMatch = param.expression.match(FOR_LOOP_TRACK_PATTERN);
21591
- // For now loops can only have a `track` parameter.
21592
- // We may want to rework this later if we add more.
21593
- if (trackMatch === null) {
21594
- errors.push(new ParseError(param.sourceSpan, `Unrecognized loop paramater "${param.expression}"`));
21596
+ if (trackMatch !== null) {
21597
+ if (result.trackBy !== null) {
21598
+ errors.push(new ParseError(param.sourceSpan, 'For loop can only have one "track" expression'));
21599
+ }
21600
+ else {
21601
+ result.trackBy = parseBlockParameterToBinding(param, bindingParser, trackMatch[1]);
21602
+ }
21603
+ continue;
21604
+ }
21605
+ errors.push(new ParseError(param.sourceSpan, `Unrecognized loop paramater "${param.expression}"`));
21606
+ }
21607
+ return result;
21608
+ }
21609
+ /** Parses the `let` parameter of a `for` loop block. */
21610
+ function parseLetParameter(sourceSpan, expression, context, errors) {
21611
+ const parts = expression.split(',');
21612
+ for (const part of parts) {
21613
+ const expressionParts = part.split('=');
21614
+ const name = expressionParts.length === 2 ? expressionParts[0].trim() : '';
21615
+ const variableName = expressionParts.length === 2 ? expressionParts[1].trim() : '';
21616
+ if (name.length === 0 || variableName.length === 0) {
21617
+ errors.push(new ParseError(sourceSpan, `Invalid for loop "let" parameter. Parameter should match the pattern "<name> = <variable name>"`));
21595
21618
  }
21596
- else if (result.trackBy !== null) {
21597
- errors.push(new ParseError(param.sourceSpan, 'For loop can only have one "track" expression'));
21619
+ else if (!ALLOWED_FOR_LOOP_LET_VARIABLES.has(variableName)) {
21620
+ errors.push(new ParseError(sourceSpan, `Unknown "let" parameter variable "${variableName}". The allowed variables are: ${Array.from(ALLOWED_FOR_LOOP_LET_VARIABLES).join(', ')}`));
21621
+ }
21622
+ else if (context.hasOwnProperty(variableName)) {
21623
+ errors.push(new ParseError(sourceSpan, `Duplicate "let" parameter variable "${variableName}"`));
21598
21624
  }
21599
21625
  else {
21600
- result.trackBy = trackMatch[1].trim();
21626
+ context[variableName] = name;
21601
21627
  }
21602
21628
  }
21603
- return result;
21604
21629
  }
21605
21630
  /** Checks that the shape of a `if` block is valid. Returns an array of errors. */
21606
21631
  function validateIfBlock(ast) {
@@ -21665,17 +21690,34 @@ function validateSwitchBlock(ast) {
21665
21690
  }
21666
21691
  return errors;
21667
21692
  }
21668
- /** Parses a block parameter into a binding AST. */
21669
- function parseBlockParameterToBinding(ast, bindingParser, start = 0) {
21670
- return bindingParser.parseBinding(ast.expression.slice(start), false, ast.sourceSpan, ast.sourceSpan.start.offset + start);
21693
+ function parseBlockParameterToBinding(ast, bindingParser, part = 0) {
21694
+ let start;
21695
+ let end;
21696
+ if (typeof part === 'number') {
21697
+ start = part;
21698
+ end = ast.expression.length;
21699
+ }
21700
+ else {
21701
+ // Note: `lastIndexOf` here should be enough to know the start index of the expression,
21702
+ // because we know that it'll be at the end of the param. Ideally we could use the `d`
21703
+ // flag when matching via regex and get the index from `match.indices`, but it's unclear
21704
+ // if we can use it yet since it's a relatively new feature. See:
21705
+ // https://github.com/tc39/proposal-regexp-match-indices
21706
+ start = Math.max(0, ast.expression.lastIndexOf(part));
21707
+ end = start + part.length;
21708
+ }
21709
+ return bindingParser.parseBinding(ast.expression.slice(start, end), false, ast.sourceSpan, ast.sourceSpan.start.offset + start);
21671
21710
  }
21672
21711
  /** Parses the parameter of a conditional block (`if` or `else if`). */
21673
- function parseConditionalBlockParameters(block, errors, bindingParser, primaryExpressionStart) {
21712
+ function parseConditionalBlockParameters(block, errors, bindingParser) {
21674
21713
  if (block.parameters.length === 0) {
21675
21714
  errors.push(new ParseError(block.sourceSpan, 'Conditional block does not have an expression'));
21676
21715
  return null;
21677
21716
  }
21678
- const expression = parseBlockParameterToBinding(block.parameters[0], bindingParser, primaryExpressionStart);
21717
+ const isPrimaryIfBlock = block.name === 'if';
21718
+ const expression =
21719
+ // Expressions for `{:else if}` blocks start at 2 to skip the `if` from the expression.
21720
+ parseBlockParameterToBinding(block.parameters[0], bindingParser, isPrimaryIfBlock ? 0 : 2);
21679
21721
  let expressionAlias = null;
21680
21722
  // Start from 1 since we processed the first parameter already.
21681
21723
  for (let i = 1; i < block.parameters.length; i++) {
@@ -21686,6 +21728,9 @@ function parseConditionalBlockParameters(block, errors, bindingParser, primaryEx
21686
21728
  if (aliasMatch === null) {
21687
21729
  errors.push(new ParseError(param.sourceSpan, `Unrecognized conditional paramater "${param.expression}"`));
21688
21730
  }
21731
+ else if (!isPrimaryIfBlock) {
21732
+ errors.push(new ParseError(param.sourceSpan, '"as" expression is only allowed on the primary "if" block'));
21733
+ }
21689
21734
  else if (expressionAlias !== null) {
21690
21735
  errors.push(new ParseError(param.sourceSpan, 'Conditional can only have one "as" expression'));
21691
21736
  }
@@ -23760,6 +23805,11 @@ class TemplateDefinitionBuilder {
23760
23805
  this._currentIndex = 0;
23761
23806
  /** Temporary variable declarations generated from visiting pipes, literals, etc. */
23762
23807
  this._tempVariables = [];
23808
+ /**
23809
+ * Temporary variable used to store state between control flow instructions.
23810
+ * Should be accessed via the `allocateControlFlowTempVariable` method.
23811
+ */
23812
+ this._controlFlowTempVariable = null;
23763
23813
  /**
23764
23814
  * List of callbacks to build nested templates. Nested templates must not be visited until
23765
23815
  * after the parent template has finished visiting all of its nodes. This ensures that all
@@ -23793,6 +23843,8 @@ class TemplateDefinitionBuilder {
23793
23843
  this.visitDeferredBlockError = invalid;
23794
23844
  this.visitDeferredBlockLoading = invalid;
23795
23845
  this.visitDeferredBlockPlaceholder = invalid;
23846
+ this.visitIfBlockBranch = invalid;
23847
+ this.visitSwitchBlockCase = invalid;
23796
23848
  this._bindingScope = parentBindingScope.nestedScope(level);
23797
23849
  // Turn the relative context file path into an identifier by replacing non-alphanumeric
23798
23850
  // characters with underscores.
@@ -23905,8 +23957,16 @@ class TemplateDefinitionBuilder {
23905
23957
  registerContextVariables(variable$1) {
23906
23958
  const scopedName = this._bindingScope.freshReferenceName();
23907
23959
  const retrievalLevel = this.level;
23960
+ const isDirect = variable$1.value === DIRECT_CONTEXT_REFERENCE;
23908
23961
  const lhs = variable(variable$1.name + scopedName);
23909
- this._bindingScope.set(retrievalLevel, variable$1.name, lhs, 1 /* DeclarationPriority.CONTEXT */, (scope, relativeLevel) => {
23962
+ this._bindingScope.set(retrievalLevel, variable$1.name, scope => {
23963
+ // If we're at the top level and we're referring to the context variable directly, we
23964
+ // can do so through the implicit receiver, instead of renaming it. Note that this does
23965
+ // not apply to listeners, because they need to restore the context.
23966
+ return isDirect && scope.bindingLevel === retrievalLevel && !scope.isListenerScope() ?
23967
+ variable(CONTEXT_NAME) :
23968
+ lhs;
23969
+ }, 1 /* DeclarationPriority.CONTEXT */, (scope, relativeLevel) => {
23910
23970
  let rhs;
23911
23971
  if (scope.bindingLevel === retrievalLevel) {
23912
23972
  if (scope.isListenerScope() && scope.hasRestoreViewVariable()) {
@@ -23917,6 +23977,11 @@ class TemplateDefinitionBuilder {
23917
23977
  rhs = variable(RESTORED_VIEW_CONTEXT_NAME);
23918
23978
  scope.notifyRestoredViewContextUse();
23919
23979
  }
23980
+ else if (isDirect) {
23981
+ // If we have a direct read of the context at the top level we don't need to
23982
+ // declare any variables and we can refer to it directly.
23983
+ return [];
23984
+ }
23920
23985
  else {
23921
23986
  // e.g. ctx
23922
23987
  rhs = variable(CONTEXT_NAME);
@@ -23927,8 +23992,11 @@ class TemplateDefinitionBuilder {
23927
23992
  // e.g. ctx_r0 OR x(2);
23928
23993
  rhs = sharedCtxVar ? sharedCtxVar : generateNextContextExpr(relativeLevel);
23929
23994
  }
23930
- // e.g. const $item$ = x(2).$implicit;
23931
- return [lhs.set(rhs.prop(variable$1.value || IMPLICIT_REFERENCE)).toConstDecl()];
23995
+ return [
23996
+ // e.g. const $items$ = x(2) for direct context references and
23997
+ // const $item$ = x(2).$implicit for indirect ones.
23998
+ lhs.set(isDirect ? rhs : rhs.prop(variable$1.value || IMPLICIT_REFERENCE)).toConstDecl()
23999
+ ];
23932
24000
  });
23933
24001
  }
23934
24002
  i18nAppendBindings(expressions) {
@@ -24490,6 +24558,118 @@ class TemplateDefinitionBuilder {
24490
24558
  }
24491
24559
  return null;
24492
24560
  }
24561
+ visitIfBlock(block) {
24562
+ // We have to process the block in two steps: once here and again in the update instruction
24563
+ // callback in order to generate the correct expressions when pipes or pure functions are
24564
+ // used inside the branch expressions.
24565
+ const branchData = block.branches.map(({ expression, expressionAlias, children, sourceSpan }) => {
24566
+ let processedExpression = null;
24567
+ if (expression !== null) {
24568
+ processedExpression = expression.visit(this._valueConverter);
24569
+ this.allocateBindingSlots(processedExpression);
24570
+ }
24571
+ // If the branch has an alias, it'll be assigned directly to the container's context.
24572
+ // We define a variable referring directly to the context so that any nested usages can be
24573
+ // rewritten to refer to it.
24574
+ const variables = expressionAlias ?
24575
+ [new Variable(expressionAlias, DIRECT_CONTEXT_REFERENCE, sourceSpan, sourceSpan)] :
24576
+ undefined;
24577
+ return {
24578
+ index: this.createEmbeddedTemplateFn(null, children, '_Conditional', sourceSpan, variables),
24579
+ expression: processedExpression,
24580
+ alias: expressionAlias
24581
+ };
24582
+ });
24583
+ // Use the index of the first block as the index for the entire container.
24584
+ const containerIndex = branchData[0].index;
24585
+ const paramsCallback = () => {
24586
+ let contextVariable = null;
24587
+ const generateBranch = (branchIndex) => {
24588
+ // If we've gone beyond the last branch, return the special -1 value which means that no
24589
+ // view will be rendered. Note that we don't need to reset the context here, because -1
24590
+ // won't render a view so the passed-in context won't be captured.
24591
+ if (branchIndex > branchData.length - 1) {
24592
+ return literal(-1);
24593
+ }
24594
+ const { index, expression, alias } = branchData[branchIndex];
24595
+ // If the branch has no expression, it means that it's the final `else`.
24596
+ // Return its index and stop the recursion. Assumes that there's only one
24597
+ // `else` condition and that it's the last branch.
24598
+ if (expression === null) {
24599
+ return literal(index);
24600
+ }
24601
+ let comparisonTarget;
24602
+ if (alias) {
24603
+ // If the branch is aliased, we need to assign the expression value to the temporary
24604
+ // variable and then pass it into `conditional`. E.g. for the expression:
24605
+ // `{#if foo(); as alias}...{/if}` we have to generate:
24606
+ // ```
24607
+ // let temp;
24608
+ // conditional(0, (temp = ctx.foo()) ? 0 : -1, temp);
24609
+ // ```
24610
+ contextVariable = this.allocateControlFlowTempVariable();
24611
+ comparisonTarget = contextVariable.set(this.convertPropertyBinding(expression));
24612
+ }
24613
+ else {
24614
+ comparisonTarget = this.convertPropertyBinding(expression);
24615
+ }
24616
+ return comparisonTarget.conditional(literal(index), generateBranch(branchIndex + 1));
24617
+ };
24618
+ const params = [literal(containerIndex), generateBranch(0)];
24619
+ if (contextVariable !== null) {
24620
+ params.push(contextVariable);
24621
+ }
24622
+ return params;
24623
+ };
24624
+ this.updateInstructionWithAdvance(containerIndex, block.branches[0].sourceSpan, Identifiers.conditional, paramsCallback);
24625
+ }
24626
+ visitSwitchBlock(block) {
24627
+ // Allocate slots for the primary block expression.
24628
+ const blockExpression = block.expression.visit(this._valueConverter);
24629
+ this.allocateBindingSlots(blockExpression);
24630
+ // We have to process the block in two steps: once here and again in the update instruction
24631
+ // callback in order to generate the correct expressions when pipes or pure functions are used.
24632
+ const caseData = block.cases.map(currentCase => {
24633
+ const index = this.createEmbeddedTemplateFn(null, currentCase.children, '_Case', currentCase.sourceSpan);
24634
+ let expression = null;
24635
+ if (currentCase.expression !== null) {
24636
+ expression = currentCase.expression.visit(this._valueConverter);
24637
+ this.allocateBindingSlots(expression);
24638
+ }
24639
+ return { index, expression };
24640
+ });
24641
+ // Use the index of the first block as the index for the entire container.
24642
+ const containerIndex = caseData[0].index;
24643
+ this.updateInstructionWithAdvance(containerIndex, block.sourceSpan, Identifiers.conditional, () => {
24644
+ const generateCases = (caseIndex) => {
24645
+ // If we've gone beyond the last branch, return the special -1
24646
+ // value which means that no view will be rendered.
24647
+ if (caseIndex > caseData.length - 1) {
24648
+ return literal(-1);
24649
+ }
24650
+ const { index, expression } = caseData[caseIndex];
24651
+ // If the case has no expression, it means that it's the `default` case.
24652
+ // Return its index and stop the recursion. Assumes that there's only one
24653
+ // `default` condition and that it's defined last.
24654
+ if (expression === null) {
24655
+ return literal(index);
24656
+ }
24657
+ // If this is the very first comparison, we need to assign the value of the primary
24658
+ // expression as a part of the comparison so the remaining cases can reuse it. In practice
24659
+ // this looks as follows:
24660
+ // ```
24661
+ // let temp;
24662
+ // conditional(1, (temp = ctx.foo) === 1 ? 1 : temp === 2 ? 2 : temp === 3 ? 3 : 4);
24663
+ // ```
24664
+ const comparisonTarget = caseIndex === 0 ?
24665
+ this.allocateControlFlowTempVariable().set(this.convertPropertyBinding(blockExpression)) :
24666
+ this.allocateControlFlowTempVariable();
24667
+ return comparisonTarget.identical(this.convertPropertyBinding(expression))
24668
+ .conditional(literal(index), generateCases(caseIndex + 1));
24669
+ };
24670
+ return [literal(containerIndex), generateCases(0)];
24671
+ });
24672
+ }
24493
24673
  visitDeferredBlock(deferred) {
24494
24674
  const { loading, placeholder, error, triggers, prefetchTriggers } = deferred;
24495
24675
  const primaryTemplateIndex = this.createEmbeddedTemplateFn(null, deferred.children, '_Defer', deferred.sourceSpan);
@@ -24593,13 +24773,9 @@ class TemplateDefinitionBuilder {
24593
24773
  allocateDataSlot() {
24594
24774
  return this._dataIndex++;
24595
24775
  }
24596
- // TODO: implement control flow instructions
24597
- visitSwitchBlock(block) { }
24598
- visitSwitchBlockCase(block) { }
24776
+ // TODO: implement for loop instructions
24599
24777
  visitForLoopBlock(block) { }
24600
24778
  visitForLoopBlockEmpty(block) { }
24601
- visitIfBlock(block) { }
24602
- visitIfBlockBranch(block) { }
24603
24779
  getConstCount() {
24604
24780
  return this._dataIndex;
24605
24781
  }
@@ -24724,6 +24900,21 @@ class TemplateDefinitionBuilder {
24724
24900
  this._tempVariables.push(...stmts);
24725
24901
  return args;
24726
24902
  }
24903
+ /**
24904
+ * Creates and returns a variable that can be used to
24905
+ * store the state between control flow instructions.
24906
+ */
24907
+ allocateControlFlowTempVariable() {
24908
+ // Note: the assumption here is that we'll only need one temporary variable for all control
24909
+ // flow instructions. It's expected that any instructions will overwrite it before passing it
24910
+ // into the parameters.
24911
+ if (this._controlFlowTempVariable === null) {
24912
+ const name = `${this.contextName}_contFlowTmp`;
24913
+ this._tempVariables.push(new DeclareVarStmt(name));
24914
+ this._controlFlowTempVariable = variable(name);
24915
+ }
24916
+ return this._controlFlowTempVariable;
24917
+ }
24727
24918
  /**
24728
24919
  * Prepares all attribute expression values for the `TAttributes` array.
24729
24920
  *
@@ -25045,7 +25236,7 @@ class BindingScope {
25045
25236
  if (value.declareLocalCallback && !value.declare) {
25046
25237
  value.declare = true;
25047
25238
  }
25048
- return value.lhs;
25239
+ return typeof value.lhs === 'function' ? value.lhs(this) : value.lhs;
25049
25240
  }
25050
25241
  current = current.parent;
25051
25242
  }
@@ -25149,7 +25340,8 @@ class BindingScope {
25149
25340
  const componentValue = this.map.get(SHARED_CONTEXT_KEY + 0);
25150
25341
  componentValue.declare = true;
25151
25342
  this.maybeRestoreView();
25152
- return componentValue.lhs.prop(name);
25343
+ const lhs = typeof componentValue.lhs === 'function' ? componentValue.lhs(this) : componentValue.lhs;
25344
+ return name === DIRECT_CONTEXT_REFERENCE ? lhs : lhs.prop(name);
25153
25345
  }
25154
25346
  maybeRestoreView() {
25155
25347
  // View restoration is required for listener instructions inside embedded views, because
@@ -26898,7 +27090,7 @@ function publishFacade(global) {
26898
27090
  * @description
26899
27091
  * Entry point for all public APIs of the compiler package.
26900
27092
  */
26901
- const VERSION = new Version('17.0.0-next.0');
27093
+ const VERSION = new Version('17.0.0-next.1');
26902
27094
 
26903
27095
  class CompilerConfig {
26904
27096
  constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, useJit = true, missingTranslation = null, preserveWhitespaces, strictInjectionParameters } = {}) {
@@ -29056,7 +29248,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
29056
29248
  function compileDeclareClassMetadata(metadata) {
29057
29249
  const definitionMap = new DefinitionMap();
29058
29250
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
29059
- definitionMap.set('version', literal('17.0.0-next.0'));
29251
+ definitionMap.set('version', literal('17.0.0-next.1'));
29060
29252
  definitionMap.set('ngImport', importExpr(Identifiers.core));
29061
29253
  definitionMap.set('type', metadata.type);
29062
29254
  definitionMap.set('decorators', metadata.decorators);
@@ -29142,7 +29334,7 @@ function compileDependency(dep) {
29142
29334
  *
29143
29335
  * Do not include any prerelease in these versions as they are ignored.
29144
29336
  */
29145
- const MINIMUM_PARTIAL_LINKER_VERSION$5 = '14.0.0';
29337
+ const MINIMUM_PARTIAL_LINKER_VERSION$5 = '16.1.0';
29146
29338
  /**
29147
29339
  * Compile a directive declaration defined by the `R3DirectiveMetadata`.
29148
29340
  */
@@ -29158,8 +29350,13 @@ function compileDeclareDirectiveFromMetadata(meta) {
29158
29350
  */
29159
29351
  function createDirectiveDefinitionMap(meta) {
29160
29352
  const definitionMap = new DefinitionMap();
29161
- definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
29162
- definitionMap.set('version', literal('17.0.0-next.0'));
29353
+ const hasTransformFunctions = Object.values(meta.inputs).some(input => input.transformFunction !== null);
29354
+ // Note: in order to allow consuming Angular libraries that have been compiled with 16.1+ in
29355
+ // Angular 16.0, we only force a minimum version of 16.1 if input transform feature as introduced
29356
+ // in 16.1 is actually used.
29357
+ const minVersion = hasTransformFunctions ? MINIMUM_PARTIAL_LINKER_VERSION$5 : '14.0.0';
29358
+ definitionMap.set('minVersion', literal(minVersion));
29359
+ definitionMap.set('version', literal('17.0.0-next.1'));
29163
29360
  // e.g. `type: MyDirective`
29164
29361
  definitionMap.set('type', meta.type.value);
29165
29362
  if (meta.isStandalone) {
@@ -29390,7 +29587,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
29390
29587
  function compileDeclareFactoryFunction(meta) {
29391
29588
  const definitionMap = new DefinitionMap();
29392
29589
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
29393
- definitionMap.set('version', literal('17.0.0-next.0'));
29590
+ definitionMap.set('version', literal('17.0.0-next.1'));
29394
29591
  definitionMap.set('ngImport', importExpr(Identifiers.core));
29395
29592
  definitionMap.set('type', meta.type.value);
29396
29593
  definitionMap.set('deps', compileDependencies(meta.deps));
@@ -29425,7 +29622,7 @@ function compileDeclareInjectableFromMetadata(meta) {
29425
29622
  function createInjectableDefinitionMap(meta) {
29426
29623
  const definitionMap = new DefinitionMap();
29427
29624
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
29428
- definitionMap.set('version', literal('17.0.0-next.0'));
29625
+ definitionMap.set('version', literal('17.0.0-next.1'));
29429
29626
  definitionMap.set('ngImport', importExpr(Identifiers.core));
29430
29627
  definitionMap.set('type', meta.type.value);
29431
29628
  // Only generate providedIn property if it has a non-null value
@@ -29476,7 +29673,7 @@ function compileDeclareInjectorFromMetadata(meta) {
29476
29673
  function createInjectorDefinitionMap(meta) {
29477
29674
  const definitionMap = new DefinitionMap();
29478
29675
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
29479
- definitionMap.set('version', literal('17.0.0-next.0'));
29676
+ definitionMap.set('version', literal('17.0.0-next.1'));
29480
29677
  definitionMap.set('ngImport', importExpr(Identifiers.core));
29481
29678
  definitionMap.set('type', meta.type.value);
29482
29679
  definitionMap.set('providers', meta.providers);
@@ -29509,7 +29706,7 @@ function createNgModuleDefinitionMap(meta) {
29509
29706
  throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
29510
29707
  }
29511
29708
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
29512
- definitionMap.set('version', literal('17.0.0-next.0'));
29709
+ definitionMap.set('version', literal('17.0.0-next.1'));
29513
29710
  definitionMap.set('ngImport', importExpr(Identifiers.core));
29514
29711
  definitionMap.set('type', meta.type.value);
29515
29712
  // We only generate the keys in the metadata if the arrays contain values.
@@ -29560,7 +29757,7 @@ function compileDeclarePipeFromMetadata(meta) {
29560
29757
  function createPipeDefinitionMap(meta) {
29561
29758
  const definitionMap = new DefinitionMap();
29562
29759
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
29563
- definitionMap.set('version', literal('17.0.0-next.0'));
29760
+ definitionMap.set('version', literal('17.0.0-next.1'));
29564
29761
  definitionMap.set('ngImport', importExpr(Identifiers.core));
29565
29762
  // e.g. `type: MyPipe`
29566
29763
  definitionMap.set('type', meta.type.value);