@angular/compiler 16.2.0-next.4 → 16.2.0

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.
Files changed (75) hide show
  1. package/esm2022/src/expression_parser/parser.mjs +2 -1
  2. package/esm2022/src/jit_compiler_facade.mjs +15 -6
  3. package/esm2022/src/ml_parser/parser.mjs +6 -3
  4. package/esm2022/src/output/output_ast.mjs +2 -2
  5. package/esm2022/src/render3/partial/class_metadata.mjs +1 -1
  6. package/esm2022/src/render3/partial/directive.mjs +1 -1
  7. package/esm2022/src/render3/partial/factory.mjs +1 -1
  8. package/esm2022/src/render3/partial/injectable.mjs +1 -1
  9. package/esm2022/src/render3/partial/injector.mjs +1 -1
  10. package/esm2022/src/render3/partial/ng_module.mjs +1 -1
  11. package/esm2022/src/render3/partial/pipe.mjs +1 -1
  12. package/esm2022/src/render3/r3_identifiers.mjs +2 -1
  13. package/esm2022/src/render3/view/api.mjs +1 -1
  14. package/esm2022/src/render3/view/compiler.mjs +24 -8
  15. package/esm2022/src/render3/view/t2_api.mjs +1 -1
  16. package/esm2022/src/render3/view/t2_binder.mjs +47 -13
  17. package/esm2022/src/render3/view/template.mjs +41 -5
  18. package/esm2022/src/template/pipeline/ir/index.mjs +2 -1
  19. package/esm2022/src/template/pipeline/ir/src/element.mjs +23 -19
  20. package/esm2022/src/template/pipeline/ir/src/enums.mjs +59 -30
  21. package/esm2022/src/template/pipeline/ir/src/expression.mjs +50 -21
  22. package/esm2022/src/template/pipeline/ir/src/operations.mjs +26 -10
  23. package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +64 -5
  24. package/esm2022/src/template/pipeline/ir/src/ops/host.mjs +21 -0
  25. package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +50 -88
  26. package/esm2022/src/template/pipeline/ir/src/traits.mjs +1 -1
  27. package/esm2022/src/template/pipeline/src/compilation.mjs +87 -48
  28. package/esm2022/src/template/pipeline/src/conversion.mjs +23 -1
  29. package/esm2022/src/template/pipeline/src/emit.mjs +105 -30
  30. package/esm2022/src/template/pipeline/src/ingest.mjs +92 -104
  31. package/esm2022/src/template/pipeline/src/instruction.mjs +86 -55
  32. package/esm2022/src/template/pipeline/src/phases/align_pipe_variadic_var_offset.mjs +1 -1
  33. package/esm2022/src/template/pipeline/src/phases/any_cast.mjs +30 -0
  34. package/esm2022/src/template/pipeline/src/phases/attribute_extraction.mjs +60 -49
  35. package/esm2022/src/template/pipeline/src/phases/binding_specialization.mjs +64 -0
  36. package/esm2022/src/template/pipeline/src/phases/chaining.mjs +9 -5
  37. package/esm2022/src/template/pipeline/src/phases/const_collection.mjs +1 -1
  38. package/esm2022/src/template/pipeline/src/phases/empty_elements.mjs +1 -1
  39. package/esm2022/src/template/pipeline/src/phases/expand_safe_reads.mjs +18 -12
  40. package/esm2022/src/template/pipeline/src/phases/generate_advance.mjs +2 -2
  41. package/esm2022/src/template/pipeline/src/phases/generate_variables.mjs +6 -6
  42. package/esm2022/src/template/pipeline/src/phases/host_style_property_parsing.mjs +64 -0
  43. package/esm2022/src/template/pipeline/src/phases/local_refs.mjs +1 -1
  44. package/esm2022/src/template/pipeline/src/phases/namespace.mjs +26 -0
  45. package/esm2022/src/template/pipeline/src/phases/naming.mjs +32 -15
  46. package/esm2022/src/template/pipeline/src/phases/next_context_merging.mjs +1 -1
  47. package/esm2022/src/template/pipeline/src/phases/ng_container.mjs +1 -1
  48. package/esm2022/src/template/pipeline/src/phases/no_listeners_on_templates.mjs +36 -0
  49. package/esm2022/src/template/pipeline/src/phases/nonbindable.mjs +47 -0
  50. package/esm2022/src/template/pipeline/src/phases/nullish_coalescing.mjs +5 -5
  51. package/esm2022/src/template/pipeline/src/phases/pipe_creation.mjs +1 -1
  52. package/esm2022/src/template/pipeline/src/phases/pipe_variadic.mjs +1 -1
  53. package/esm2022/src/template/pipeline/src/phases/property_ordering.mjs +30 -13
  54. package/esm2022/src/template/pipeline/src/phases/pure_function_extraction.mjs +4 -4
  55. package/esm2022/src/template/pipeline/src/phases/pure_literal_structures.mjs +3 -3
  56. package/esm2022/src/template/pipeline/src/phases/reify.mjs +94 -57
  57. package/esm2022/src/template/pipeline/src/phases/remove_empty_bindings.mjs +28 -0
  58. package/esm2022/src/template/pipeline/src/phases/resolve_contexts.mjs +4 -4
  59. package/esm2022/src/template/pipeline/src/phases/resolve_dollar_event.mjs +33 -0
  60. package/esm2022/src/template/pipeline/src/phases/resolve_names.mjs +13 -9
  61. package/esm2022/src/template/pipeline/src/phases/resolve_sanitizers.mjs +58 -0
  62. package/esm2022/src/template/pipeline/src/phases/save_restore_view.mjs +3 -3
  63. package/esm2022/src/template/pipeline/src/phases/slot_allocation.mjs +1 -1
  64. package/esm2022/src/template/pipeline/src/phases/style_binding_specialization.mjs +42 -0
  65. package/esm2022/src/template/pipeline/src/phases/temporary_variables.mjs +40 -20
  66. package/esm2022/src/template/pipeline/src/phases/var_counting.mjs +33 -30
  67. package/esm2022/src/template/pipeline/src/phases/variable_optimization.mjs +10 -9
  68. package/esm2022/src/template/pipeline/src/util/elements.mjs +22 -0
  69. package/esm2022/src/version.mjs +1 -1
  70. package/fesm2022/compiler.mjs +1762 -943
  71. package/fesm2022/compiler.mjs.map +1 -1
  72. package/fesm2022/testing.mjs +1 -1
  73. package/index.d.ts +60 -5
  74. package/package.json +2 -2
  75. package/testing/index.d.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v16.2.0-next.4
2
+ * @license Angular v16.2.0
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -1784,7 +1784,7 @@ class ReadKeyExpr extends Expression {
1784
1784
  return new WriteKeyExpr(this.receiver, this.index, value, null, this.sourceSpan);
1785
1785
  }
1786
1786
  clone() {
1787
- return new ReadKeyExpr(this.receiver, this.index.clone(), this.type, this.sourceSpan);
1787
+ return new ReadKeyExpr(this.receiver.clone(), this.index.clone(), this.type, this.sourceSpan);
1788
1788
  }
1789
1789
  }
1790
1790
  class LiteralArrayExpr extends Expression {
@@ -2613,6 +2613,7 @@ class Identifiers {
2613
2613
  static { this.nextContext = { name: 'ɵɵnextContext', moduleName: CORE }; }
2614
2614
  static { this.resetView = { name: 'ɵɵresetView', moduleName: CORE }; }
2615
2615
  static { this.templateCreate = { name: 'ɵɵtemplate', moduleName: CORE }; }
2616
+ static { this.defer = { name: 'ɵɵdefer', moduleName: CORE }; }
2616
2617
  static { this.text = { name: 'ɵɵtext', moduleName: CORE }; }
2617
2618
  static { this.enableBindings = { name: 'ɵɵenableBindings', moduleName: CORE }; }
2618
2619
  static { this.disableBindings = { name: 'ɵɵdisableBindings', moduleName: CORE }; }
@@ -6239,7 +6240,7 @@ class LiteralMap extends AST {
6239
6240
  return visitor.visitLiteralMap(this, context);
6240
6241
  }
6241
6242
  }
6242
- class Interpolation extends AST {
6243
+ class Interpolation$1 extends AST {
6243
6244
  constructor(span, sourceSpan, strings, expressions) {
6244
6245
  super(span, sourceSpan);
6245
6246
  this.strings = strings;
@@ -6486,7 +6487,7 @@ class AstTransformer {
6486
6487
  return ast;
6487
6488
  }
6488
6489
  visitInterpolation(ast, context) {
6489
- return new Interpolation(ast.span, ast.sourceSpan, ast.strings, this.visitAll(ast.expressions));
6490
+ return new Interpolation$1(ast.span, ast.sourceSpan, ast.strings, this.visitAll(ast.expressions));
6490
6491
  }
6491
6492
  visitLiteralPrimitive(ast, context) {
6492
6493
  return new LiteralPrimitive(ast.span, ast.sourceSpan, ast.value);
@@ -6569,7 +6570,7 @@ class AstMemoryEfficientTransformer {
6569
6570
  visitInterpolation(ast, context) {
6570
6571
  const expressions = this.visitAll(ast.expressions);
6571
6572
  if (expressions !== ast.expressions)
6572
- return new Interpolation(ast.span, ast.sourceSpan, ast.strings, expressions);
6573
+ return new Interpolation$1(ast.span, ast.sourceSpan, ast.strings, expressions);
6573
6574
  return ast;
6574
6575
  }
6575
6576
  visitLiteralPrimitive(ast, context) {
@@ -8652,33 +8653,37 @@ function mergeNsAndName(prefix, localName) {
8652
8653
  /**
8653
8654
  * Enumeration of the types of attributes which can be applied to an element.
8654
8655
  */
8655
- var ElementAttributeKind;
8656
- (function (ElementAttributeKind) {
8656
+ var BindingKind;
8657
+ (function (BindingKind) {
8657
8658
  /**
8658
8659
  * Static attributes.
8659
8660
  */
8660
- ElementAttributeKind[ElementAttributeKind["Attribute"] = 0] = "Attribute";
8661
+ BindingKind[BindingKind["Attribute"] = 0] = "Attribute";
8661
8662
  /**
8662
8663
  * Class bindings.
8663
8664
  */
8664
- ElementAttributeKind[ElementAttributeKind["Class"] = 1] = "Class";
8665
+ BindingKind[BindingKind["ClassName"] = 1] = "ClassName";
8665
8666
  /**
8666
8667
  * Style bindings.
8667
8668
  */
8668
- ElementAttributeKind[ElementAttributeKind["Style"] = 2] = "Style";
8669
+ BindingKind[BindingKind["StyleProperty"] = 2] = "StyleProperty";
8669
8670
  /**
8670
- * Dynamic property or attribute bindings.
8671
+ * Dynamic property bindings.
8671
8672
  */
8672
- ElementAttributeKind[ElementAttributeKind["Binding"] = 3] = "Binding";
8673
+ BindingKind[BindingKind["Property"] = 3] = "Property";
8673
8674
  /**
8674
- * Attributes on a template node.
8675
+ * Property or attribute bindings on a template.
8675
8676
  */
8676
- ElementAttributeKind[ElementAttributeKind["Template"] = 4] = "Template";
8677
+ BindingKind[BindingKind["Template"] = 4] = "Template";
8677
8678
  /**
8678
8679
  * Internationalized attributes.
8679
8680
  */
8680
- ElementAttributeKind[ElementAttributeKind["I18n"] = 5] = "I18n";
8681
- })(ElementAttributeKind || (ElementAttributeKind = {}));
8681
+ BindingKind[BindingKind["I18n"] = 5] = "I18n";
8682
+ /**
8683
+ * TODO: Consider how Animations are handled, and if they should be a distinct BindingKind.
8684
+ */
8685
+ BindingKind[BindingKind["Animation"] = 6] = "Animation";
8686
+ })(BindingKind || (BindingKind = {}));
8682
8687
  const FLYWEIGHT_ARRAY = Object.freeze([]);
8683
8688
  /**
8684
8689
  * Container for all of the various kinds of attributes which are applied on an element.
@@ -8690,22 +8695,22 @@ class ElementAttributes {
8690
8695
  this.projectAs = null;
8691
8696
  }
8692
8697
  get attributes() {
8693
- return this.byKind.get(ElementAttributeKind.Attribute) ?? FLYWEIGHT_ARRAY;
8698
+ return this.byKind.get(BindingKind.Attribute) ?? FLYWEIGHT_ARRAY;
8694
8699
  }
8695
8700
  get classes() {
8696
- return this.byKind.get(ElementAttributeKind.Class) ?? FLYWEIGHT_ARRAY;
8701
+ return this.byKind.get(BindingKind.ClassName) ?? FLYWEIGHT_ARRAY;
8697
8702
  }
8698
8703
  get styles() {
8699
- return this.byKind.get(ElementAttributeKind.Style) ?? FLYWEIGHT_ARRAY;
8704
+ return this.byKind.get(BindingKind.StyleProperty) ?? FLYWEIGHT_ARRAY;
8700
8705
  }
8701
8706
  get bindings() {
8702
- return this.byKind.get(ElementAttributeKind.Binding) ?? FLYWEIGHT_ARRAY;
8707
+ return this.byKind.get(BindingKind.Property) ?? FLYWEIGHT_ARRAY;
8703
8708
  }
8704
8709
  get template() {
8705
- return this.byKind.get(ElementAttributeKind.Template) ?? FLYWEIGHT_ARRAY;
8710
+ return this.byKind.get(BindingKind.Template) ?? FLYWEIGHT_ARRAY;
8706
8711
  }
8707
8712
  get i18n() {
8708
- return this.byKind.get(ElementAttributeKind.I18n) ?? FLYWEIGHT_ARRAY;
8713
+ return this.byKind.get(BindingKind.I18n) ?? FLYWEIGHT_ARRAY;
8709
8714
  }
8710
8715
  add(kind, name, value) {
8711
8716
  if (this.known.has(name)) {
@@ -8714,7 +8719,7 @@ class ElementAttributes {
8714
8719
  this.known.add(name);
8715
8720
  const array = this.arrayFor(kind);
8716
8721
  array.push(...getAttributeNameLiterals$1(name));
8717
- if (kind === ElementAttributeKind.Attribute || kind === ElementAttributeKind.Style) {
8722
+ if (kind === BindingKind.Attribute || kind === BindingKind.StyleProperty) {
8718
8723
  if (value === null) {
8719
8724
  throw Error('Attribute & style element attributes must have a value');
8720
8725
  }
@@ -8792,70 +8797,73 @@ var OpKind;
8792
8797
  * An operation to end an `ng-container`.
8793
8798
  */
8794
8799
  OpKind[OpKind["ContainerEnd"] = 9] = "ContainerEnd";
8800
+ /**
8801
+ * An operation disable binding for subsequent elements, which are descendants of a non-bindable
8802
+ * node.
8803
+ */
8804
+ OpKind[OpKind["DisableBindings"] = 10] = "DisableBindings";
8805
+ /**
8806
+ * An operation to re-enable binding, after it was previously disabled.
8807
+ */
8808
+ OpKind[OpKind["EnableBindings"] = 11] = "EnableBindings";
8795
8809
  /**
8796
8810
  * An operation to render a text node.
8797
8811
  */
8798
- OpKind[OpKind["Text"] = 10] = "Text";
8812
+ OpKind[OpKind["Text"] = 12] = "Text";
8799
8813
  /**
8800
8814
  * An operation declaring an event listener for an element.
8801
8815
  */
8802
- OpKind[OpKind["Listener"] = 11] = "Listener";
8816
+ OpKind[OpKind["Listener"] = 13] = "Listener";
8803
8817
  /**
8804
8818
  * An operation to interpolate text into a text node.
8805
8819
  */
8806
- OpKind[OpKind["InterpolateText"] = 12] = "InterpolateText";
8820
+ OpKind[OpKind["InterpolateText"] = 14] = "InterpolateText";
8821
+ /**
8822
+ * An intermediate binding op, that has not yet been processed into an individual property,
8823
+ * attribute, style, etc.
8824
+ */
8825
+ OpKind[OpKind["Binding"] = 15] = "Binding";
8807
8826
  /**
8808
8827
  * An operation to bind an expression to a property of an element.
8809
8828
  */
8810
- OpKind[OpKind["Property"] = 13] = "Property";
8829
+ OpKind[OpKind["Property"] = 16] = "Property";
8811
8830
  /**
8812
8831
  * An operation to bind an expression to a style property of an element.
8813
8832
  */
8814
- OpKind[OpKind["StyleProp"] = 14] = "StyleProp";
8833
+ OpKind[OpKind["StyleProp"] = 17] = "StyleProp";
8815
8834
  /**
8816
8835
  * An operation to bind an expression to a class property of an element.
8817
8836
  */
8818
- OpKind[OpKind["ClassProp"] = 15] = "ClassProp";
8837
+ OpKind[OpKind["ClassProp"] = 18] = "ClassProp";
8819
8838
  /**
8820
8839
  * An operation to bind an expression to the styles of an element.
8821
8840
  */
8822
- OpKind[OpKind["StyleMap"] = 16] = "StyleMap";
8841
+ OpKind[OpKind["StyleMap"] = 19] = "StyleMap";
8823
8842
  /**
8824
8843
  * An operation to bind an expression to the classes of an element.
8825
8844
  */
8826
- OpKind[OpKind["ClassMap"] = 17] = "ClassMap";
8827
- /**
8828
- * An operation to interpolate text into a property binding.
8829
- */
8830
- OpKind[OpKind["InterpolateProperty"] = 18] = "InterpolateProperty";
8831
- /**
8832
- * An operation to interpolate text into a style property binding.
8833
- */
8834
- OpKind[OpKind["InterpolateStyleProp"] = 19] = "InterpolateStyleProp";
8835
- /**
8836
- * An operation to interpolate text into a style mapping.
8837
- */
8838
- OpKind[OpKind["InterpolateStyleMap"] = 20] = "InterpolateStyleMap";
8839
- /**
8840
- * An operation to interpolate text into a class mapping.
8841
- */
8842
- OpKind[OpKind["InterpolateClassMap"] = 21] = "InterpolateClassMap";
8845
+ OpKind[OpKind["ClassMap"] = 20] = "ClassMap";
8843
8846
  /**
8844
8847
  * An operation to advance the runtime's implicit slot context during the update phase of a view.
8845
8848
  */
8846
- OpKind[OpKind["Advance"] = 22] = "Advance";
8849
+ OpKind[OpKind["Advance"] = 21] = "Advance";
8847
8850
  /**
8848
8851
  * An operation to instantiate a pipe.
8849
8852
  */
8850
- OpKind[OpKind["Pipe"] = 23] = "Pipe";
8853
+ OpKind[OpKind["Pipe"] = 22] = "Pipe";
8851
8854
  /**
8852
8855
  * An operation to associate an attribute with an element.
8853
8856
  */
8854
- OpKind[OpKind["Attribute"] = 24] = "Attribute";
8857
+ OpKind[OpKind["Attribute"] = 23] = "Attribute";
8855
8858
  /**
8856
- * An operation to interpolate text into an attribute binding.
8859
+ * A host binding property.
8857
8860
  */
8858
- OpKind[OpKind["InterpolateAttribute"] = 25] = "InterpolateAttribute";
8861
+ OpKind[OpKind["HostProperty"] = 24] = "HostProperty";
8862
+ /**
8863
+ * A namespace change, which causes the subsequent elements to be processed as either HTML or SVG.
8864
+ */
8865
+ OpKind[OpKind["Namespace"] = 25] = "Namespace";
8866
+ // TODO: Add Host Listeners, and possibly other host ops also.
8859
8867
  })(OpKind || (OpKind = {}));
8860
8868
  /**
8861
8869
  * Distinguishes different kinds of IR expressions.
@@ -8938,6 +8946,10 @@ var ExpressionKind;
8938
8946
  * A reference to a temporary variable.
8939
8947
  */
8940
8948
  ExpressionKind[ExpressionKind["ReadTemporaryExpr"] = 18] = "ReadTemporaryExpr";
8949
+ /**
8950
+ * An expression representing a sanitizer function.
8951
+ */
8952
+ ExpressionKind[ExpressionKind["SanitizerExpr"] = 19] = "SanitizerExpr";
8941
8953
  })(ExpressionKind || (ExpressionKind = {}));
8942
8954
  /**
8943
8955
  * Distinguishes between different kinds of `SemanticVariable`s.
@@ -8957,6 +8969,28 @@ var SemanticVariableKind;
8957
8969
  */
8958
8970
  SemanticVariableKind[SemanticVariableKind["SavedView"] = 2] = "SavedView";
8959
8971
  })(SemanticVariableKind || (SemanticVariableKind = {}));
8972
+ /**
8973
+ * Whether to compile in compatibilty mode. In compatibility mode, the template pipeline will
8974
+ * attempt to match the output of `TemplateDefinitionBuilder` as exactly as possible, at the cost of
8975
+ * producing quirky or larger code in some cases.
8976
+ */
8977
+ var CompatibilityMode;
8978
+ (function (CompatibilityMode) {
8979
+ CompatibilityMode[CompatibilityMode["Normal"] = 0] = "Normal";
8980
+ CompatibilityMode[CompatibilityMode["TemplateDefinitionBuilder"] = 1] = "TemplateDefinitionBuilder";
8981
+ })(CompatibilityMode || (CompatibilityMode = {}));
8982
+ /**
8983
+ * Represents functions used to sanitize different pieces of a template.
8984
+ */
8985
+ var SanitizerFn;
8986
+ (function (SanitizerFn) {
8987
+ SanitizerFn[SanitizerFn["Html"] = 0] = "Html";
8988
+ SanitizerFn[SanitizerFn["Script"] = 1] = "Script";
8989
+ SanitizerFn[SanitizerFn["Style"] = 2] = "Style";
8990
+ SanitizerFn[SanitizerFn["Url"] = 3] = "Url";
8991
+ SanitizerFn[SanitizerFn["ResourceUrl"] = 4] = "ResourceUrl";
8992
+ SanitizerFn[SanitizerFn["IframeAttribute"] = 5] = "IframeAttribute";
8993
+ })(SanitizerFn || (SanitizerFn = {}));
8960
8994
 
8961
8995
  /**
8962
8996
  * Marker symbol for `ConsumesSlotOpTrait`.
@@ -9042,6 +9076,181 @@ function hasUsesSlotIndexTrait(value) {
9042
9076
  return value[UsesSlotIndex] === true;
9043
9077
  }
9044
9078
 
9079
+ /**
9080
+ * Create a `StatementOp`.
9081
+ */
9082
+ function createStatementOp(statement) {
9083
+ return {
9084
+ kind: OpKind.Statement,
9085
+ statement,
9086
+ ...NEW_OP,
9087
+ };
9088
+ }
9089
+ /**
9090
+ * Create a `VariableOp`.
9091
+ */
9092
+ function createVariableOp(xref, variable, initializer) {
9093
+ return {
9094
+ kind: OpKind.Variable,
9095
+ xref,
9096
+ variable,
9097
+ initializer,
9098
+ ...NEW_OP,
9099
+ };
9100
+ }
9101
+ /**
9102
+ * Static structure shared by all operations.
9103
+ *
9104
+ * Used as a convenience via the spread operator (`...NEW_OP`) when creating new operations, and
9105
+ * ensures the fields are always in the same order.
9106
+ */
9107
+ const NEW_OP = {
9108
+ debugListId: null,
9109
+ prev: null,
9110
+ next: null,
9111
+ };
9112
+
9113
+ /**
9114
+ * Create an `InterpolationTextOp`.
9115
+ */
9116
+ function createInterpolateTextOp(xref, interpolation, sourceSpan) {
9117
+ return {
9118
+ kind: OpKind.InterpolateText,
9119
+ target: xref,
9120
+ interpolation,
9121
+ sourceSpan,
9122
+ ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
9123
+ ...TRAIT_CONSUMES_VARS,
9124
+ ...NEW_OP,
9125
+ };
9126
+ }
9127
+ class Interpolation {
9128
+ constructor(strings, expressions) {
9129
+ this.strings = strings;
9130
+ this.expressions = expressions;
9131
+ }
9132
+ }
9133
+ /**
9134
+ * Create a `BindingOp`, not yet transformed into a particular type of binding.
9135
+ */
9136
+ function createBindingOp(target, kind, name, expression, unit, securityContext, isTemplate, sourceSpan) {
9137
+ return {
9138
+ kind: OpKind.Binding,
9139
+ bindingKind: kind,
9140
+ target,
9141
+ name,
9142
+ expression,
9143
+ unit,
9144
+ securityContext,
9145
+ isTemplate,
9146
+ sourceSpan,
9147
+ ...NEW_OP,
9148
+ };
9149
+ }
9150
+ /**
9151
+ * Create a `PropertyOp`.
9152
+ */
9153
+ function createPropertyOp(target, name, expression, isAnimationTrigger, securityContext, isTemplate, sourceSpan) {
9154
+ return {
9155
+ kind: OpKind.Property,
9156
+ target,
9157
+ name,
9158
+ expression,
9159
+ isAnimationTrigger,
9160
+ securityContext,
9161
+ sanitizer: null,
9162
+ isTemplate,
9163
+ sourceSpan,
9164
+ ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
9165
+ ...TRAIT_CONSUMES_VARS,
9166
+ ...NEW_OP,
9167
+ };
9168
+ }
9169
+ /** Create a `StylePropOp`. */
9170
+ function createStylePropOp(xref, name, expression, unit, sourceSpan) {
9171
+ return {
9172
+ kind: OpKind.StyleProp,
9173
+ target: xref,
9174
+ name,
9175
+ expression,
9176
+ unit,
9177
+ sourceSpan,
9178
+ ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
9179
+ ...TRAIT_CONSUMES_VARS,
9180
+ ...NEW_OP,
9181
+ };
9182
+ }
9183
+ /**
9184
+ * Create a `ClassPropOp`.
9185
+ */
9186
+ function createClassPropOp(xref, name, expression, sourceSpan) {
9187
+ return {
9188
+ kind: OpKind.ClassProp,
9189
+ target: xref,
9190
+ name,
9191
+ expression,
9192
+ sourceSpan,
9193
+ ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
9194
+ ...TRAIT_CONSUMES_VARS,
9195
+ ...NEW_OP,
9196
+ };
9197
+ }
9198
+ /** Create a `StyleMapOp`. */
9199
+ function createStyleMapOp(xref, expression, sourceSpan) {
9200
+ return {
9201
+ kind: OpKind.StyleMap,
9202
+ target: xref,
9203
+ expression,
9204
+ sourceSpan,
9205
+ ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
9206
+ ...TRAIT_CONSUMES_VARS,
9207
+ ...NEW_OP,
9208
+ };
9209
+ }
9210
+ /**
9211
+ * Create a `ClassMapOp`.
9212
+ */
9213
+ function createClassMapOp(xref, expression, sourceSpan) {
9214
+ return {
9215
+ kind: OpKind.ClassMap,
9216
+ target: xref,
9217
+ expression,
9218
+ sourceSpan,
9219
+ ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
9220
+ ...TRAIT_CONSUMES_VARS,
9221
+ ...NEW_OP,
9222
+ };
9223
+ }
9224
+ /**
9225
+ * Create an `AttributeOp`.
9226
+ */
9227
+ function createAttributeOp(target, name, expression, securityContext, isTemplate, sourceSpan) {
9228
+ return {
9229
+ kind: OpKind.Attribute,
9230
+ target,
9231
+ name,
9232
+ expression,
9233
+ securityContext,
9234
+ sanitizer: null,
9235
+ isTemplate,
9236
+ sourceSpan,
9237
+ ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
9238
+ ...TRAIT_CONSUMES_VARS,
9239
+ ...NEW_OP,
9240
+ };
9241
+ }
9242
+ /**
9243
+ * Create an `AdvanceOp`.
9244
+ */
9245
+ function createAdvanceOp(delta, sourceSpan) {
9246
+ return {
9247
+ kind: OpKind.Advance,
9248
+ delta,
9249
+ sourceSpan,
9250
+ ...NEW_OP,
9251
+ };
9252
+ }
9253
+
9045
9254
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
9046
9255
  /**
9047
9256
  * Check whether a given `o.Expression` is a logical IR expression type.
@@ -9542,7 +9751,7 @@ class AssignTemporaryExpr extends ExpressionBase {
9542
9751
  this.expr = transformExpressionsInExpression(this.expr, transform, flags);
9543
9752
  }
9544
9753
  clone() {
9545
- const a = new AssignTemporaryExpr(this.expr, this.xref);
9754
+ const a = new AssignTemporaryExpr(this.expr.clone(), this.xref);
9546
9755
  a.name = this.name;
9547
9756
  return a;
9548
9757
  }
@@ -9568,6 +9777,24 @@ class ReadTemporaryExpr extends ExpressionBase {
9568
9777
  return r;
9569
9778
  }
9570
9779
  }
9780
+ class SanitizerExpr extends ExpressionBase {
9781
+ constructor(fn) {
9782
+ super();
9783
+ this.fn = fn;
9784
+ this.kind = ExpressionKind.SanitizerExpr;
9785
+ }
9786
+ visitExpression(visitor, context) { }
9787
+ isEquivalent(e) {
9788
+ return e instanceof SanitizerExpr && e.fn === this.fn;
9789
+ }
9790
+ isConstant() {
9791
+ return true;
9792
+ }
9793
+ clone() {
9794
+ return new SanitizerExpr(this.fn);
9795
+ }
9796
+ transformInternalExpressions() { }
9797
+ }
9571
9798
  /**
9572
9799
  * Visits all `Expression`s in the AST of `op` with the `visitor` function.
9573
9800
  */
@@ -9582,6 +9809,12 @@ var VisitorContextFlag;
9582
9809
  VisitorContextFlag[VisitorContextFlag["None"] = 0] = "None";
9583
9810
  VisitorContextFlag[VisitorContextFlag["InChildOperation"] = 1] = "InChildOperation";
9584
9811
  })(VisitorContextFlag || (VisitorContextFlag = {}));
9812
+ function transformExpressionsInInterpolation(interpolation, transform, flags) {
9813
+ for (let i = 0; i < interpolation.expressions.length; i++) {
9814
+ interpolation.expressions[i] =
9815
+ transformExpressionsInExpression(interpolation.expressions[i], transform, flags);
9816
+ }
9817
+ }
9585
9818
  /**
9586
9819
  * Transform all `Expression`s in the AST of `op` with the `transform` function.
9587
9820
  *
@@ -9590,34 +9823,35 @@ var VisitorContextFlag;
9590
9823
  */
9591
9824
  function transformExpressionsInOp(op, transform, flags) {
9592
9825
  switch (op.kind) {
9593
- case OpKind.Property:
9594
9826
  case OpKind.StyleProp:
9595
9827
  case OpKind.StyleMap:
9596
9828
  case OpKind.ClassProp:
9597
9829
  case OpKind.ClassMap:
9598
- op.expression = transformExpressionsInExpression(op.expression, transform, flags);
9599
- break;
9600
- case OpKind.InterpolateProperty:
9601
- case OpKind.InterpolateStyleProp:
9602
- case OpKind.InterpolateStyleMap:
9603
- case OpKind.InterpolateClassMap:
9604
- case OpKind.InterpolateText:
9605
- for (let i = 0; i < op.expressions.length; i++) {
9606
- op.expressions[i] = transformExpressionsInExpression(op.expressions[i], transform, flags);
9830
+ case OpKind.Binding:
9831
+ case OpKind.HostProperty:
9832
+ if (op.expression instanceof Interpolation) {
9833
+ transformExpressionsInInterpolation(op.expression, transform, flags);
9834
+ }
9835
+ else {
9836
+ op.expression = transformExpressionsInExpression(op.expression, transform, flags);
9607
9837
  }
9608
9838
  break;
9609
- case OpKind.Statement:
9610
- transformExpressionsInStatement(op.statement, transform, flags);
9611
- break;
9839
+ case OpKind.Property:
9612
9840
  case OpKind.Attribute:
9613
- if (op.value) {
9614
- op.value = transformExpressionsInExpression(op.value, transform, flags);
9841
+ if (op.expression instanceof Interpolation) {
9842
+ transformExpressionsInInterpolation(op.expression, transform, flags);
9615
9843
  }
9616
- break;
9617
- case OpKind.InterpolateAttribute:
9618
- for (let i = 0; i < op.expressions.length; i++) {
9619
- op.expressions[i] = transformExpressionsInExpression(op.expressions[i], transform, flags);
9844
+ else {
9845
+ op.expression = transformExpressionsInExpression(op.expression, transform, flags);
9620
9846
  }
9847
+ op.sanitizer =
9848
+ op.sanitizer && transformExpressionsInExpression(op.sanitizer, transform, flags);
9849
+ break;
9850
+ case OpKind.InterpolateText:
9851
+ transformExpressionsInInterpolation(op.interpolation, transform, flags);
9852
+ break;
9853
+ case OpKind.Statement:
9854
+ transformExpressionsInStatement(op.statement, transform, flags);
9621
9855
  break;
9622
9856
  case OpKind.Variable:
9623
9857
  op.initializer = transformExpressionsInExpression(op.initializer, transform, flags);
@@ -9634,9 +9868,12 @@ function transformExpressionsInOp(op, transform, flags) {
9634
9868
  case OpKind.ContainerStart:
9635
9869
  case OpKind.ContainerEnd:
9636
9870
  case OpKind.Template:
9871
+ case OpKind.DisableBindings:
9872
+ case OpKind.EnableBindings:
9637
9873
  case OpKind.Text:
9638
9874
  case OpKind.Pipe:
9639
9875
  case OpKind.Advance:
9876
+ case OpKind.Namespace:
9640
9877
  // These operations contain no expressions.
9641
9878
  break;
9642
9879
  default:
@@ -9907,22 +10144,38 @@ class OpList {
9907
10144
  op.next = null;
9908
10145
  }
9909
10146
  /**
9910
- * Insert `op` before `before`.
10147
+ * Insert `op` before `target`.
9911
10148
  */
9912
- static insertBefore(op, before) {
9913
- OpList.assertIsOwned(before);
9914
- if (before.prev === null) {
10149
+ static insertBefore(op, target) {
10150
+ OpList.assertIsOwned(target);
10151
+ if (target.prev === null) {
9915
10152
  throw new Error(`AssertionError: illegal operation on list start`);
9916
10153
  }
9917
10154
  OpList.assertIsNotEnd(op);
9918
10155
  OpList.assertIsUnowned(op);
9919
- op.debugListId = before.debugListId;
10156
+ op.debugListId = target.debugListId;
9920
10157
  // Just in case.
9921
10158
  op.prev = null;
9922
- before.prev.next = op;
9923
- op.prev = before.prev;
9924
- op.next = before;
9925
- before.prev = op;
10159
+ target.prev.next = op;
10160
+ op.prev = target.prev;
10161
+ op.next = target;
10162
+ target.prev = op;
10163
+ }
10164
+ /**
10165
+ * Insert `op` after `target`.
10166
+ */
10167
+ static insertAfter(op, target) {
10168
+ OpList.assertIsOwned(target);
10169
+ if (target.next === null) {
10170
+ throw new Error(`AssertionError: illegal operation on list end`);
10171
+ }
10172
+ OpList.assertIsNotEnd(op);
10173
+ OpList.assertIsUnowned(op);
10174
+ op.debugListId = target.debugListId;
10175
+ target.next.prev = op;
10176
+ op.next = target.next;
10177
+ op.prev = target;
10178
+ target.next = op;
9926
10179
  }
9927
10180
  /**
9928
10181
  * Asserts that `op` does not currently belong to a list.
@@ -9954,40 +10207,6 @@ class OpList {
9954
10207
  }
9955
10208
  }
9956
10209
 
9957
- /**
9958
- * Create a `StatementOp`.
9959
- */
9960
- function createStatementOp(statement) {
9961
- return {
9962
- kind: OpKind.Statement,
9963
- statement,
9964
- ...NEW_OP,
9965
- };
9966
- }
9967
- /**
9968
- * Create a `VariableOp`.
9969
- */
9970
- function createVariableOp(xref, variable, initializer) {
9971
- return {
9972
- kind: OpKind.Variable,
9973
- xref,
9974
- variable,
9975
- initializer,
9976
- ...NEW_OP,
9977
- };
9978
- }
9979
- /**
9980
- * Static structure shared by all operations.
9981
- *
9982
- * Used as a convenience via the spread operator (`...NEW_OP`) when creating new operations, and
9983
- * ensures the fields are always in the same order.
9984
- */
9985
- const NEW_OP = {
9986
- debugListId: null,
9987
- prev: null,
9988
- next: null,
9989
- };
9990
-
9991
10210
  /**
9992
10211
  * The set of OpKinds that represent the creation of an element or container
9993
10212
  */
@@ -10003,13 +10222,16 @@ function isElementOrContainerOp(op) {
10003
10222
  /**
10004
10223
  * Create an `ElementStartOp`.
10005
10224
  */
10006
- function createElementStartOp(tag, xref) {
10225
+ function createElementStartOp(tag, xref, namespace, sourceSpan) {
10007
10226
  return {
10008
10227
  kind: OpKind.ElementStart,
10009
10228
  xref,
10010
10229
  tag,
10011
10230
  attributes: new ElementAttributes(),
10012
10231
  localRefs: [],
10232
+ nonBindable: false,
10233
+ namespace,
10234
+ sourceSpan,
10013
10235
  ...TRAIT_CONSUMES_SLOT,
10014
10236
  ...NEW_OP,
10015
10237
  };
@@ -10017,7 +10239,7 @@ function createElementStartOp(tag, xref) {
10017
10239
  /**
10018
10240
  * Create a `TemplateOp`.
10019
10241
  */
10020
- function createTemplateOp(xref, tag) {
10242
+ function createTemplateOp(xref, tag, namespace, sourceSpan) {
10021
10243
  return {
10022
10244
  kind: OpKind.Template,
10023
10245
  xref,
@@ -10026,6 +10248,9 @@ function createTemplateOp(xref, tag) {
10026
10248
  decls: null,
10027
10249
  vars: null,
10028
10250
  localRefs: [],
10251
+ nonBindable: false,
10252
+ namespace,
10253
+ sourceSpan,
10029
10254
  ...TRAIT_CONSUMES_SLOT,
10030
10255
  ...NEW_OP,
10031
10256
  };
@@ -10033,21 +10258,37 @@ function createTemplateOp(xref, tag) {
10033
10258
  /**
10034
10259
  * Create an `ElementEndOp`.
10035
10260
  */
10036
- function createElementEndOp(xref) {
10261
+ function createElementEndOp(xref, sourceSpan) {
10037
10262
  return {
10038
10263
  kind: OpKind.ElementEnd,
10039
10264
  xref,
10265
+ sourceSpan,
10266
+ ...NEW_OP,
10267
+ };
10268
+ }
10269
+ function createDisableBindingsOp(xref) {
10270
+ return {
10271
+ kind: OpKind.DisableBindings,
10272
+ xref,
10273
+ ...NEW_OP,
10274
+ };
10275
+ }
10276
+ function createEnableBindingsOp(xref) {
10277
+ return {
10278
+ kind: OpKind.EnableBindings,
10279
+ xref,
10040
10280
  ...NEW_OP,
10041
10281
  };
10042
10282
  }
10043
10283
  /**
10044
10284
  * Create a `TextOp`.
10045
10285
  */
10046
- function createTextOp(xref, initialValue) {
10286
+ function createTextOp(xref, initialValue, sourceSpan) {
10047
10287
  return {
10048
10288
  kind: OpKind.Text,
10049
10289
  xref,
10050
10290
  initialValue,
10291
+ sourceSpan,
10051
10292
  ...TRAIT_CONSUMES_SLOT,
10052
10293
  ...NEW_OP,
10053
10294
  };
@@ -10063,208 +10304,231 @@ function createListenerOp(target, name, tag) {
10063
10304
  name,
10064
10305
  handlerOps: new OpList(),
10065
10306
  handlerFnName: null,
10307
+ consumesDollarEvent: false,
10308
+ isAnimationListener: false,
10309
+ animationPhase: null,
10066
10310
  ...NEW_OP,
10067
10311
  ...TRAIT_USES_SLOT_INDEX,
10068
10312
  };
10069
10313
  }
10070
- function createPipeOp(xref, name) {
10071
- return {
10072
- kind: OpKind.Pipe,
10073
- xref,
10074
- name,
10075
- ...NEW_OP,
10076
- ...TRAIT_CONSUMES_SLOT,
10077
- };
10078
- }
10079
-
10080
10314
  /**
10081
- * Create an `InterpolationTextOp`.
10315
+ * Create a `ListenerOp` for an animation.
10082
10316
  */
10083
- function createInterpolateTextOp(xref, strings, expressions) {
10317
+ function createListenerOpForAnimation(target, name, animationPhase, tag) {
10084
10318
  return {
10085
- kind: OpKind.InterpolateText,
10086
- target: xref,
10087
- strings,
10088
- expressions,
10089
- ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
10090
- ...TRAIT_CONSUMES_VARS,
10091
- ...NEW_OP,
10092
- };
10093
- }
10094
- /**
10095
- * Create a `PropertyOp`.
10096
- */
10097
- function createPropertyOp(xref, bindingKind, name, expression) {
10098
- return {
10099
- kind: OpKind.Property,
10100
- target: xref,
10101
- bindingKind,
10102
- name,
10103
- expression,
10104
- ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
10105
- ...TRAIT_CONSUMES_VARS,
10106
- ...NEW_OP,
10107
- };
10108
- }
10109
- /** Create a `StylePropOp`. */
10110
- function createStylePropOp(xref, name, expression, unit) {
10111
- return {
10112
- kind: OpKind.StyleProp,
10113
- target: xref,
10114
- name,
10115
- expression,
10116
- unit,
10117
- ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
10118
- ...TRAIT_CONSUMES_VARS,
10119
- ...NEW_OP,
10120
- };
10121
- }
10122
- /**
10123
- * Create a `ClassPropOp`.
10124
- */
10125
- function createClassPropOp(xref, name, expression) {
10126
- return {
10127
- kind: OpKind.ClassProp,
10128
- target: xref,
10319
+ kind: OpKind.Listener,
10320
+ target,
10321
+ tag,
10129
10322
  name,
10130
- expression,
10131
- ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
10132
- ...TRAIT_CONSUMES_VARS,
10133
- ...NEW_OP,
10134
- };
10135
- }
10136
- /** Create a `StyleMapOp`. */
10137
- function createStyleMapOp(xref, expression) {
10138
- return {
10139
- kind: OpKind.StyleMap,
10140
- target: xref,
10141
- expression,
10142
- ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
10143
- ...TRAIT_CONSUMES_VARS,
10144
- ...NEW_OP,
10145
- };
10146
- }
10147
- /**
10148
- * Create a `ClassMapOp`.
10149
- */
10150
- function createClassMapOp(xref, expression) {
10151
- return {
10152
- kind: OpKind.ClassMap,
10153
- target: xref,
10154
- expression,
10155
- ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
10156
- ...TRAIT_CONSUMES_VARS,
10323
+ handlerOps: new OpList(),
10324
+ handlerFnName: null,
10325
+ consumesDollarEvent: false,
10326
+ isAnimationListener: true,
10327
+ animationPhase,
10157
10328
  ...NEW_OP,
10329
+ ...TRAIT_USES_SLOT_INDEX,
10158
10330
  };
10159
10331
  }
10160
- /**
10161
- * Create an `AttributeOp`.
10162
- */
10163
- function createAttributeOp(target, attributeKind, name, value) {
10332
+ function createPipeOp(xref, name) {
10164
10333
  return {
10165
- kind: OpKind.Attribute,
10166
- target,
10167
- attributeKind,
10334
+ kind: OpKind.Pipe,
10335
+ xref,
10168
10336
  name,
10169
- value,
10170
- ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
10171
- ...TRAIT_CONSUMES_VARS,
10172
10337
  ...NEW_OP,
10338
+ ...TRAIT_CONSUMES_SLOT,
10173
10339
  };
10174
10340
  }
10175
10341
  /**
10176
- * Create a `InterpolateProperty`.
10342
+ * Whether the active namespace is HTML, MathML, or SVG mode.
10177
10343
  */
10178
- function createInterpolatePropertyOp(xref, bindingKind, name, strings, expressions) {
10344
+ var Namespace;
10345
+ (function (Namespace) {
10346
+ Namespace[Namespace["HTML"] = 0] = "HTML";
10347
+ Namespace[Namespace["SVG"] = 1] = "SVG";
10348
+ Namespace[Namespace["Math"] = 2] = "Math";
10349
+ })(Namespace || (Namespace = {}));
10350
+ function createNamespaceOp(namespace) {
10179
10351
  return {
10180
- kind: OpKind.InterpolateProperty,
10181
- target: xref,
10182
- bindingKind,
10183
- name,
10184
- strings,
10185
- expressions,
10186
- ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
10187
- ...TRAIT_CONSUMES_VARS,
10352
+ kind: OpKind.Namespace,
10353
+ active: namespace,
10188
10354
  ...NEW_OP,
10189
10355
  };
10190
10356
  }
10191
- function createInterpolateAttributeOp(target, attributeKind, name, strings, expressions) {
10357
+
10358
+ function createHostPropertyOp(name, expression, sourceSpan) {
10192
10359
  return {
10193
- kind: OpKind.InterpolateAttribute,
10194
- target: target,
10195
- attributeKind,
10360
+ kind: OpKind.HostProperty,
10196
10361
  name,
10197
- strings,
10198
- expressions,
10199
- ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
10362
+ expression,
10363
+ sourceSpan,
10200
10364
  ...TRAIT_CONSUMES_VARS,
10201
10365
  ...NEW_OP,
10202
10366
  };
10203
10367
  }
10368
+
10204
10369
  /**
10205
- * Create a `InterpolateStyleProp`.
10370
+ * A compilation unit is compiled into a template function.
10371
+ * Some example units are views and host bindings.
10206
10372
  */
10207
- function createInterpolateStylePropOp(xref, name, strings, expressions, unit) {
10208
- return {
10209
- kind: OpKind.InterpolateStyleProp,
10210
- target: xref,
10211
- name,
10212
- strings,
10213
- expressions,
10214
- unit,
10215
- ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
10216
- ...TRAIT_CONSUMES_VARS,
10217
- ...NEW_OP,
10218
- };
10373
+ class CompilationUnit {
10374
+ constructor(xref) {
10375
+ this.xref = xref;
10376
+ /**
10377
+ * List of creation operations for this view.
10378
+ *
10379
+ * Creation operations may internally contain other operations, including update operations.
10380
+ */
10381
+ this.create = new OpList();
10382
+ /**
10383
+ * List of update operations for this view.
10384
+ */
10385
+ this.update = new OpList();
10386
+ /**
10387
+ * Name of the function which will be generated for this unit.
10388
+ *
10389
+ * May be `null` if not yet determined.
10390
+ */
10391
+ this.fnName = null;
10392
+ /**
10393
+ * Number of variable slots used within this view, or `null` if variables have not yet been
10394
+ * counted.
10395
+ */
10396
+ this.vars = null;
10397
+ }
10398
+ /**
10399
+ * Iterate over all `ir.Op`s within this view.
10400
+ *
10401
+ * Some operations may have child operations, which this iterator will visit.
10402
+ */
10403
+ *ops() {
10404
+ for (const op of this.create) {
10405
+ yield op;
10406
+ if (op.kind === OpKind.Listener) {
10407
+ for (const listenerOp of op.handlerOps) {
10408
+ yield listenerOp;
10409
+ }
10410
+ }
10411
+ }
10412
+ for (const op of this.update) {
10413
+ yield op;
10414
+ }
10415
+ }
10219
10416
  }
10220
- /**
10221
- * Create a `InterpolateStyleMap`.
10222
- */
10223
- function createInterpolateStyleMapOp(xref, strings, expressions) {
10224
- return {
10225
- kind: OpKind.InterpolateStyleMap,
10226
- target: xref,
10227
- strings,
10228
- expressions,
10229
- ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
10230
- ...TRAIT_CONSUMES_VARS,
10231
- ...NEW_OP,
10232
- };
10417
+ class HostBindingCompilationJob extends CompilationUnit {
10418
+ // TODO: Perhaps we should accept a reference to the enclosing component, and get the name from
10419
+ // there?
10420
+ constructor(componentName, pool, compatibility) {
10421
+ super(0);
10422
+ this.componentName = componentName;
10423
+ this.pool = pool;
10424
+ this.compatibility = compatibility;
10425
+ this.fnSuffix = 'HostBindings';
10426
+ this.units = [this];
10427
+ this.nextXrefId = 1;
10428
+ }
10429
+ get job() {
10430
+ return this;
10431
+ }
10432
+ get root() {
10433
+ return this;
10434
+ }
10435
+ allocateXrefId() {
10436
+ return this.nextXrefId++;
10437
+ }
10233
10438
  }
10234
10439
  /**
10235
- * Create a `InterpolateStyleMap`.
10440
+ * Compilation-in-progress of a whole component's template, including the main template and any
10441
+ * embedded views or host bindings.
10236
10442
  */
10237
- function createInterpolateClassMapOp(xref, strings, expressions) {
10238
- return {
10239
- kind: OpKind.InterpolateClassMap,
10240
- target: xref,
10241
- strings,
10242
- expressions,
10243
- ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
10244
- ...TRAIT_CONSUMES_VARS,
10245
- ...NEW_OP,
10246
- };
10443
+ class ComponentCompilationJob {
10444
+ get units() {
10445
+ return this.views.values();
10446
+ }
10447
+ constructor(componentName, pool, compatibility) {
10448
+ this.componentName = componentName;
10449
+ this.pool = pool;
10450
+ this.compatibility = compatibility;
10451
+ this.fnSuffix = 'Template';
10452
+ /**
10453
+ * Tracks the next `ir.XrefId` which can be assigned as template structures are ingested.
10454
+ */
10455
+ this.nextXrefId = 0;
10456
+ /**
10457
+ * Map of view IDs to `ViewCompilation`s.
10458
+ */
10459
+ this.views = new Map();
10460
+ /**
10461
+ * Constant expressions used by operations within this component's compilation.
10462
+ *
10463
+ * This will eventually become the `consts` array in the component definition.
10464
+ */
10465
+ this.consts = [];
10466
+ // Allocate the root view.
10467
+ const root = new ViewCompilationUnit(this, this.allocateXrefId(), null);
10468
+ this.views.set(root.xref, root);
10469
+ this.root = root;
10470
+ }
10471
+ /**
10472
+ * Add a `ViewCompilation` for a new embedded view to this compilation.
10473
+ */
10474
+ allocateView(parent) {
10475
+ const view = new ViewCompilationUnit(this, this.allocateXrefId(), parent);
10476
+ this.views.set(view.xref, view);
10477
+ return view;
10478
+ }
10479
+ /**
10480
+ * Generate a new unique `ir.XrefId` in this job.
10481
+ */
10482
+ allocateXrefId() {
10483
+ return this.nextXrefId++;
10484
+ }
10485
+ /**
10486
+ * Add a constant `o.Expression` to the compilation and return its index in the `consts` array.
10487
+ */
10488
+ addConst(newConst) {
10489
+ for (let idx = 0; idx < this.consts.length; idx++) {
10490
+ if (this.consts[idx].isEquivalent(newConst)) {
10491
+ return idx;
10492
+ }
10493
+ }
10494
+ const idx = this.consts.length;
10495
+ this.consts.push(newConst);
10496
+ return idx;
10497
+ }
10247
10498
  }
10248
10499
  /**
10249
- * Create an `AdvanceOp`.
10500
+ * Compilation-in-progress of an individual view within a template.
10250
10501
  */
10251
- function createAdvanceOp(delta) {
10252
- return {
10253
- kind: OpKind.Advance,
10254
- delta,
10255
- ...NEW_OP,
10256
- };
10502
+ class ViewCompilationUnit extends CompilationUnit {
10503
+ constructor(job, xref, parent) {
10504
+ super(xref);
10505
+ this.job = job;
10506
+ this.parent = parent;
10507
+ /**
10508
+ * Map of declared variables available within this view to the property on the context object
10509
+ * which they alias.
10510
+ */
10511
+ this.contextVariables = new Map();
10512
+ /**
10513
+ * Number of declaration slots used within this view, or `null` if slots have not yet been
10514
+ * allocated.
10515
+ */
10516
+ this.decls = null;
10517
+ }
10518
+ get compatibility() {
10519
+ return this.job.compatibility;
10520
+ }
10257
10521
  }
10258
10522
 
10259
10523
  /**
10260
10524
  * Counts the number of variable slots used within each view, and stores that on the view itself, as
10261
10525
  * well as propagates it to the `ir.TemplateOp` for embedded views.
10262
10526
  */
10263
- function phaseVarCounting(cpl) {
10527
+ function phaseVarCounting(job) {
10264
10528
  // First, count the vars used in each view, and update the view-level counter.
10265
- for (const [_, view] of cpl.views) {
10529
+ for (const unit of job.units) {
10266
10530
  let varCount = 0;
10267
- for (const op of view.ops()) {
10531
+ for (const op of unit.ops()) {
10268
10532
  if (hasConsumesVarsTrait(op)) {
10269
10533
  varCount += varsUsedByOp(op);
10270
10534
  }
@@ -10281,17 +10545,19 @@ function phaseVarCounting(cpl) {
10281
10545
  }
10282
10546
  });
10283
10547
  }
10284
- view.vars = varCount;
10548
+ unit.vars = varCount;
10285
10549
  }
10286
- // Add var counts for each view to the `ir.TemplateOp` which declares that view (if the view is an
10287
- // embedded view).
10288
- for (const [_, view] of cpl.views) {
10289
- for (const op of view.create) {
10290
- if (op.kind !== OpKind.Template) {
10291
- continue;
10550
+ if (job instanceof ComponentCompilationJob) {
10551
+ // Add var counts for each view to the `ir.TemplateOp` which declares that view (if the view is
10552
+ // an embedded view).
10553
+ for (const view of job.views.values()) {
10554
+ for (const op of view.create) {
10555
+ if (op.kind !== OpKind.Template) {
10556
+ continue;
10557
+ }
10558
+ const childView = job.views.get(op.xref);
10559
+ op.vars = childView.vars;
10292
10560
  }
10293
- const childView = cpl.views.get(op.xref);
10294
- op.vars = childView.vars;
10295
10561
  }
10296
10562
  }
10297
10563
  }
@@ -10300,32 +10566,32 @@ function phaseVarCounting(cpl) {
10300
10566
  * count the variables used by any particular `op`.
10301
10567
  */
10302
10568
  function varsUsedByOp(op) {
10569
+ let slots;
10303
10570
  switch (op.kind) {
10304
10571
  case OpKind.Property:
10572
+ case OpKind.HostProperty:
10305
10573
  case OpKind.Attribute:
10306
- // Property & attribute bindings use 1 variable slot.
10307
- return 1;
10574
+ // All of these bindings use 1 variable slot, plus 1 slot for every interpolated expression,
10575
+ // if any.
10576
+ slots = 1;
10577
+ if (op.expression instanceof Interpolation) {
10578
+ slots += op.expression.expressions.length;
10579
+ }
10580
+ return slots;
10308
10581
  case OpKind.StyleProp:
10309
10582
  case OpKind.ClassProp:
10310
10583
  case OpKind.StyleMap:
10311
10584
  case OpKind.ClassMap:
10312
- // Style & class bindings use 2 variable slots.
10313
- return 2;
10585
+ // Style & class bindings use 2 variable slots, plus 1 slot for every interpolated expression,
10586
+ // if any.
10587
+ slots = 2;
10588
+ if (op.expression instanceof Interpolation) {
10589
+ slots += op.expression.expressions.length;
10590
+ }
10591
+ return slots;
10314
10592
  case OpKind.InterpolateText:
10315
10593
  // `ir.InterpolateTextOp`s use a variable slot for each dynamic expression.
10316
- return op.expressions.length;
10317
- case OpKind.InterpolateProperty:
10318
- // `ir.InterpolatePropertyOp`s use a variable slot for each dynamic expression, plus one for
10319
- // the result.
10320
- return 1 + op.expressions.length;
10321
- case OpKind.InterpolateAttribute:
10322
- // One variable slot for each dynamic expression, plus one for the result.
10323
- return 1 + op.expressions.length;
10324
- case OpKind.InterpolateStyleProp:
10325
- case OpKind.InterpolateStyleMap:
10326
- case OpKind.InterpolateClassMap:
10327
- // One variable slot for each dynamic expression, plus two for binding the result.
10328
- return 2 + op.expressions.length;
10594
+ return op.interpolation.expressions.length;
10329
10595
  default:
10330
10596
  throw new Error(`Unhandled op: ${OpKind[op.kind]}`);
10331
10597
  }
@@ -10376,39 +10642,109 @@ function phaseAlignPipeVariadicVarOffset(cpl) {
10376
10642
  }
10377
10643
 
10378
10644
  /**
10379
- * Find all attribute and binding ops, and collect them into the ElementAttribute structures.
10380
- * In cases where no instruction needs to be generated for the attribute or binding, it is removed.
10645
+ * Find any function calls to `$any`, excluding `this.$any`, and delete them.
10381
10646
  */
10382
- function phaseAttributeExtraction(cpl, compatibility) {
10647
+ function phaseFindAnyCasts(cpl) {
10383
10648
  for (const [_, view] of cpl.views) {
10384
- populateElementAttributes(view, compatibility);
10649
+ for (const op of view.ops()) {
10650
+ transformExpressionsInOp(op, removeAnys, VisitorContextFlag.None);
10651
+ }
10385
10652
  }
10386
10653
  }
10387
- /**
10388
- * Looks up an element in the given map by xref ID.
10389
- */
10390
- function lookupElement(elements, xref) {
10391
- const el = elements.get(xref);
10392
- if (el === undefined) {
10393
- throw new Error('All attributes should have an element-like target.');
10654
+ function removeAnys(e) {
10655
+ if (e instanceof InvokeFunctionExpr && e.fn instanceof LexicalReadExpr &&
10656
+ e.fn.name === '$any') {
10657
+ if (e.args.length !== 1) {
10658
+ throw new Error('The $any builtin function expects exactly one argument.');
10659
+ }
10660
+ return e.args[0];
10394
10661
  }
10395
- return el;
10662
+ return e;
10396
10663
  }
10664
+
10397
10665
  /**
10398
- * Removes the op if its expression is empty.
10666
+ * Parses string representation of a style and converts it into object literal.
10667
+ *
10668
+ * @param value string representation of style as used in the `style` attribute in HTML.
10669
+ * Example: `color: red; height: auto`.
10670
+ * @returns An array of style property name and value pairs, e.g. `['color', 'red', 'height',
10671
+ * 'auto']`
10399
10672
  */
10400
- function removeIfExpressionIsEmpty(op, expression) {
10401
- if (expression instanceof EmptyExpr) {
10402
- OpList.remove(op);
10403
- return true;
10673
+ function parse(value) {
10674
+ // we use a string array here instead of a string map
10675
+ // because a string-map is not guaranteed to retain the
10676
+ // order of the entries whereas a string array can be
10677
+ // constructed in a [key, value, key, value] format.
10678
+ const styles = [];
10679
+ let i = 0;
10680
+ let parenDepth = 0;
10681
+ let quote = 0 /* Char.QuoteNone */;
10682
+ let valueStart = 0;
10683
+ let propStart = 0;
10684
+ let currentProp = null;
10685
+ while (i < value.length) {
10686
+ const token = value.charCodeAt(i++);
10687
+ switch (token) {
10688
+ case 40 /* Char.OpenParen */:
10689
+ parenDepth++;
10690
+ break;
10691
+ case 41 /* Char.CloseParen */:
10692
+ parenDepth--;
10693
+ break;
10694
+ case 39 /* Char.QuoteSingle */:
10695
+ // valueStart needs to be there since prop values don't
10696
+ // have quotes in CSS
10697
+ if (quote === 0 /* Char.QuoteNone */) {
10698
+ quote = 39 /* Char.QuoteSingle */;
10699
+ }
10700
+ else if (quote === 39 /* Char.QuoteSingle */ && value.charCodeAt(i - 1) !== 92 /* Char.BackSlash */) {
10701
+ quote = 0 /* Char.QuoteNone */;
10702
+ }
10703
+ break;
10704
+ case 34 /* Char.QuoteDouble */:
10705
+ // same logic as above
10706
+ if (quote === 0 /* Char.QuoteNone */) {
10707
+ quote = 34 /* Char.QuoteDouble */;
10708
+ }
10709
+ else if (quote === 34 /* Char.QuoteDouble */ && value.charCodeAt(i - 1) !== 92 /* Char.BackSlash */) {
10710
+ quote = 0 /* Char.QuoteNone */;
10711
+ }
10712
+ break;
10713
+ case 58 /* Char.Colon */:
10714
+ if (!currentProp && parenDepth === 0 && quote === 0 /* Char.QuoteNone */) {
10715
+ currentProp = hyphenate$1(value.substring(propStart, i - 1).trim());
10716
+ valueStart = i;
10717
+ }
10718
+ break;
10719
+ case 59 /* Char.Semicolon */:
10720
+ if (currentProp && valueStart > 0 && parenDepth === 0 && quote === 0 /* Char.QuoteNone */) {
10721
+ const styleVal = value.substring(valueStart, i - 1).trim();
10722
+ styles.push(currentProp, styleVal);
10723
+ propStart = i;
10724
+ valueStart = 0;
10725
+ currentProp = null;
10726
+ }
10727
+ break;
10728
+ }
10404
10729
  }
10405
- return false;
10730
+ if (currentProp && valueStart) {
10731
+ const styleVal = value.slice(valueStart).trim();
10732
+ styles.push(currentProp, styleVal);
10733
+ }
10734
+ return styles;
10406
10735
  }
10736
+ function hyphenate$1(value) {
10737
+ return value
10738
+ .replace(/[a-z][A-Z]/g, v => {
10739
+ return v.charAt(0) + '-' + v.charAt(1);
10740
+ })
10741
+ .toLowerCase();
10742
+ }
10743
+
10407
10744
  /**
10408
- * Populates the ElementAttributes map for the given view, and removes ops for any bindings that do
10409
- * not need further processing.
10745
+ * Gets a map of all elements in the given view by their xref id.
10410
10746
  */
10411
- function populateElementAttributes(view, compatibility) {
10747
+ function getElementsByXrefId(view) {
10412
10748
  const elements = new Map();
10413
10749
  for (const op of view.create) {
10414
10750
  if (!isElementOrContainerOp(op)) {
@@ -10416,61 +10752,170 @@ function populateElementAttributes(view, compatibility) {
10416
10752
  }
10417
10753
  elements.set(op.xref, op);
10418
10754
  }
10755
+ return elements;
10756
+ }
10757
+
10758
+ /**
10759
+ * Find all attribute and binding ops, and collect them into the ElementAttribute structures.
10760
+ * In cases where no instruction needs to be generated for the attribute or binding, it is removed.
10761
+ */
10762
+ function phaseAttributeExtraction(cpl) {
10763
+ for (const [_, view] of cpl.views) {
10764
+ populateElementAttributes(view);
10765
+ }
10766
+ }
10767
+ /**
10768
+ * Looks up an element in the given map by xref ID.
10769
+ */
10770
+ function lookupElement$2(elements, xref) {
10771
+ const el = elements.get(xref);
10772
+ if (el === undefined) {
10773
+ throw new Error('All attributes should have an element-like target.');
10774
+ }
10775
+ return el;
10776
+ }
10777
+ /**
10778
+ * Populates the ElementAttributes map for the given view, and removes ops for any bindings that do
10779
+ * not need further processing.
10780
+ */
10781
+ function populateElementAttributes(view) {
10782
+ const elements = getElementsByXrefId(view);
10419
10783
  for (const op of view.ops()) {
10420
10784
  let ownerOp;
10421
10785
  switch (op.kind) {
10422
10786
  case OpKind.Attribute:
10423
- ownerOp = lookupElement(elements, op.target);
10424
- assertIsElementAttributes(ownerOp.attributes);
10425
- // The old compiler only extracted string constants, so we emulate that behavior in
10426
- // compaitiblity mode, otherwise we optimize more aggressively.
10427
- let extractable = compatibility ?
10428
- (op.value instanceof LiteralExpr && typeof op.value.value === 'string') :
10429
- (op.value.isConstant());
10430
- // We don't need to generate instructions for attributes that can be extracted as consts.
10431
- if (extractable) {
10432
- ownerOp.attributes.add(op.attributeKind, op.name, op.value);
10433
- OpList.remove(op);
10434
- }
10787
+ extractAttributeOp(view, op, elements);
10435
10788
  break;
10436
10789
  case OpKind.Property:
10437
- ownerOp = lookupElement(elements, op.target);
10438
- assertIsElementAttributes(ownerOp.attributes);
10439
- removeIfExpressionIsEmpty(op, op.expression);
10440
- ownerOp.attributes.add(op.bindingKind, op.name, null);
10441
- break;
10442
- case OpKind.InterpolateProperty:
10443
- ownerOp = lookupElement(elements, op.target);
10790
+ if (op.isAnimationTrigger) {
10791
+ continue; // Don't extract animation properties.
10792
+ }
10793
+ ownerOp = lookupElement$2(elements, op.target);
10444
10794
  assertIsElementAttributes(ownerOp.attributes);
10445
- ownerOp.attributes.add(op.bindingKind, op.name, null);
10795
+ ownerOp.attributes.add(op.isTemplate ? BindingKind.Template : BindingKind.Property, op.name, null);
10446
10796
  break;
10447
10797
  case OpKind.StyleProp:
10448
10798
  case OpKind.ClassProp:
10449
- ownerOp = lookupElement(elements, op.target);
10799
+ ownerOp = lookupElement$2(elements, op.target);
10450
10800
  assertIsElementAttributes(ownerOp.attributes);
10451
- // The old compiler treated empty style bindings as regular bindings for the purpose of
10452
- // directive matching. That behavior is incorrect, but we emulate it in compatibility mode.
10453
- if (removeIfExpressionIsEmpty(op, op.expression) && compatibility) {
10454
- ownerOp.attributes.add(ElementAttributeKind.Binding, op.name, null);
10801
+ // Empty StyleProperty and ClassName expressions are treated differently depending on
10802
+ // compatibility mode.
10803
+ if (view.compatibility === CompatibilityMode.TemplateDefinitionBuilder &&
10804
+ op.expression instanceof EmptyExpr) {
10805
+ // The old compiler treated empty style bindings as regular bindings for the purpose of
10806
+ // directive matching. That behavior is incorrect, but we emulate it in compatibility
10807
+ // mode.
10808
+ ownerOp.attributes.add(BindingKind.Property, op.name, null);
10455
10809
  }
10456
10810
  break;
10457
10811
  case OpKind.Listener:
10458
- ownerOp = lookupElement(elements, op.target);
10459
- assertIsElementAttributes(ownerOp.attributes);
10460
- ownerOp.attributes.add(ElementAttributeKind.Binding, op.name, null);
10461
- // We don't need to generate instructions for listeners on templates.
10462
- if (ownerOp.kind === OpKind.Template) {
10463
- OpList.remove(op);
10812
+ if (op.isAnimationListener) {
10813
+ continue; // Don't extract animation listeners.
10464
10814
  }
10815
+ ownerOp = lookupElement$2(elements, op.target);
10816
+ assertIsElementAttributes(ownerOp.attributes);
10817
+ ownerOp.attributes.add(BindingKind.Property, op.name, null);
10465
10818
  break;
10466
10819
  }
10467
10820
  }
10468
10821
  }
10822
+ function isStringLiteral(expr) {
10823
+ return expr instanceof LiteralExpr && typeof expr.value === 'string';
10824
+ }
10825
+ function extractAttributeOp(view, op, elements) {
10826
+ if (op.expression instanceof Interpolation) {
10827
+ return;
10828
+ }
10829
+ const ownerOp = lookupElement$2(elements, op.target);
10830
+ assertIsElementAttributes(ownerOp.attributes);
10831
+ if (op.name === 'style' && isStringLiteral(op.expression)) {
10832
+ // TemplateDefinitionBuilder did not extract style attributes that had a security context.
10833
+ if (view.compatibility === CompatibilityMode.TemplateDefinitionBuilder &&
10834
+ op.securityContext !== SecurityContext.NONE) {
10835
+ return;
10836
+ }
10837
+ // Extract style attributes.
10838
+ const parsedStyles = parse(op.expression.value);
10839
+ for (let i = 0; i < parsedStyles.length - 1; i += 2) {
10840
+ ownerOp.attributes.add(BindingKind.StyleProperty, parsedStyles[i], literal(parsedStyles[i + 1]));
10841
+ }
10842
+ OpList.remove(op);
10843
+ }
10844
+ else {
10845
+ // The old compiler only extracted string constants, so we emulate that behavior in
10846
+ // compaitiblity mode, otherwise we optimize more aggressively.
10847
+ let extractable = view.compatibility === CompatibilityMode.TemplateDefinitionBuilder ?
10848
+ (op.expression instanceof LiteralExpr && typeof op.expression.value === 'string') :
10849
+ op.expression.isConstant();
10850
+ // We don't need to generate instructions for attributes that can be extracted as consts.
10851
+ if (extractable) {
10852
+ ownerOp.attributes.add(op.isTemplate ? BindingKind.Template : BindingKind.Attribute, op.name, op.expression);
10853
+ OpList.remove(op);
10854
+ }
10855
+ }
10856
+ }
10857
+
10858
+ /**
10859
+ * Looks up an element in the given map by xref ID.
10860
+ */
10861
+ function lookupElement$1(elements, xref) {
10862
+ const el = elements.get(xref);
10863
+ if (el === undefined) {
10864
+ throw new Error('All attributes should have an element-like target.');
10865
+ }
10866
+ return el;
10867
+ }
10868
+ function phaseBindingSpecialization(job) {
10869
+ const elements = new Map();
10870
+ for (const unit of job.units) {
10871
+ for (const op of unit.create) {
10872
+ if (!isElementOrContainerOp(op)) {
10873
+ continue;
10874
+ }
10875
+ elements.set(op.xref, op);
10876
+ }
10877
+ }
10878
+ for (const unit of job.units) {
10879
+ for (const op of unit.ops()) {
10880
+ if (op.kind !== OpKind.Binding) {
10881
+ continue;
10882
+ }
10883
+ switch (op.bindingKind) {
10884
+ case BindingKind.Attribute:
10885
+ if (op.name === 'ngNonBindable') {
10886
+ OpList.remove(op);
10887
+ const target = lookupElement$1(elements, op.target);
10888
+ target.nonBindable = true;
10889
+ }
10890
+ else {
10891
+ OpList.replace(op, createAttributeOp(op.target, op.name, op.expression, op.securityContext, op.isTemplate, op.sourceSpan));
10892
+ }
10893
+ break;
10894
+ case BindingKind.Property:
10895
+ case BindingKind.Animation:
10896
+ if (job instanceof HostBindingCompilationJob) {
10897
+ // TODO: host property animations
10898
+ OpList.replace(op, createHostPropertyOp(op.name, op.expression, op.sourceSpan));
10899
+ }
10900
+ else {
10901
+ OpList.replace(op, createPropertyOp(op.target, op.name, op.expression, op.bindingKind === BindingKind.Animation, op.securityContext, op.isTemplate, op.sourceSpan));
10902
+ }
10903
+ break;
10904
+ case BindingKind.I18n:
10905
+ case BindingKind.ClassName:
10906
+ case BindingKind.StyleProperty:
10907
+ throw new Error(`Unhandled binding of kind ${BindingKind[op.bindingKind]}`);
10908
+ }
10909
+ }
10910
+ }
10911
+ }
10469
10912
 
10470
10913
  const CHAINABLE = new Set([
10471
10914
  Identifiers.elementStart,
10472
10915
  Identifiers.elementEnd,
10916
+ Identifiers.element,
10473
10917
  Identifiers.property,
10918
+ Identifiers.hostProperty,
10474
10919
  Identifiers.styleProp,
10475
10920
  Identifiers.attribute,
10476
10921
  Identifiers.stylePropInterpolate1,
@@ -10483,9 +10928,11 @@ const CHAINABLE = new Set([
10483
10928
  Identifiers.stylePropInterpolate8,
10484
10929
  Identifiers.stylePropInterpolateV,
10485
10930
  Identifiers.classProp,
10931
+ Identifiers.listener,
10486
10932
  Identifiers.elementContainerStart,
10487
10933
  Identifiers.elementContainerEnd,
10488
10934
  Identifiers.elementContainer,
10935
+ Identifiers.listener,
10489
10936
  ]);
10490
10937
  /**
10491
10938
  * Post-process a reified view compilation and convert sequential calls to chainable instructions
@@ -10504,10 +10951,10 @@ const CHAINABLE = new Set([
10504
10951
  * elementStart(0, 'div')(1, 'span');
10505
10952
  * ```
10506
10953
  */
10507
- function phaseChaining(cpl) {
10508
- for (const [_, view] of cpl.views) {
10509
- chainOperationsInList(view.create);
10510
- chainOperationsInList(view.update);
10954
+ function phaseChaining(job) {
10955
+ for (const unit of job.units) {
10956
+ chainOperationsInList(unit.create);
10957
+ chainOperationsInList(unit.update);
10511
10958
  }
10512
10959
  }
10513
10960
  function chainOperationsInList(opList) {
@@ -10628,10 +11075,10 @@ function phaseEmptyElements(cpl) {
10628
11075
  * Finds all unresolved safe read expressions, and converts them into the appropriate output AST
10629
11076
  * reads, guarded by null checks.
10630
11077
  */
10631
- function phaseExpandSafeReads(cpl, compatibility) {
10632
- for (const [_, view] of cpl.views) {
10633
- for (const op of view.ops()) {
10634
- transformExpressionsInOp(op, e => safeTransform(e, { cpl, compatibility }), VisitorContextFlag.None);
11078
+ function phaseExpandSafeReads(job) {
11079
+ for (const unit of job.units) {
11080
+ for (const op of unit.ops()) {
11081
+ transformExpressionsInOp(op, e => safeTransform(e, { job }), VisitorContextFlag.None);
10635
11082
  transformExpressionsInOp(op, ternaryTransform, VisitorContextFlag.None);
10636
11083
  }
10637
11084
  }
@@ -10696,7 +11143,9 @@ function eliminateTemporaryAssignments(e, tmps, ctx) {
10696
11143
  // temporary variables to themselves. This happens because some subexpression that the
10697
11144
  // temporary refers to, possibly through nested temporaries, has a function call. We copy that
10698
11145
  // behavior here.
10699
- return ctx.compatibility ? new AssignTemporaryExpr(read, read.xref) : read;
11146
+ return ctx.job.compatibility === CompatibilityMode.TemplateDefinitionBuilder ?
11147
+ new AssignTemporaryExpr(read, read.xref) :
11148
+ read;
10700
11149
  }
10701
11150
  return e;
10702
11151
  }, VisitorContextFlag.None);
@@ -10710,7 +11159,7 @@ function eliminateTemporaryAssignments(e, tmps, ctx) {
10710
11159
  function safeTernaryWithTemporary(guard, body, ctx) {
10711
11160
  let result;
10712
11161
  if (needsTemporaryInSafeAccess(guard)) {
10713
- const xref = ctx.cpl.allocateXrefId();
11162
+ const xref = ctx.job.allocateXrefId();
10714
11163
  result = [new AssignTemporaryExpr(guard, xref), new ReadTemporaryExpr(xref)];
10715
11164
  }
10716
11165
  else {
@@ -10724,7 +11173,8 @@ function safeTernaryWithTemporary(guard, body, ctx) {
10724
11173
  return new SafeTernaryExpr(result[0], body(result[1]));
10725
11174
  }
10726
11175
  function isSafeAccessExpression(e) {
10727
- return e instanceof SafePropertyReadExpr || e instanceof SafeKeyedReadExpr;
11176
+ return e instanceof SafePropertyReadExpr || e instanceof SafeKeyedReadExpr ||
11177
+ e instanceof SafeInvokeFunctionExpr;
10728
11178
  }
10729
11179
  function isUnsafeAccessExpression(e) {
10730
11180
  return e instanceof ReadPropExpr || e instanceof ReadKeyExpr ||
@@ -10746,10 +11196,6 @@ function deepestSafeTernary(e) {
10746
11196
  // TODO: When strict compatibility with TemplateDefinitionBuilder is not required, we can use `&&`
10747
11197
  // instead to save some code size.
10748
11198
  function safeTransform(e, ctx) {
10749
- if (e instanceof SafeInvokeFunctionExpr) {
10750
- // TODO: Implement safe function calls in a subsequent commit.
10751
- return new InvokeFunctionExpr(e.receiver, e.args);
10752
- }
10753
11199
  if (!isAccessExpression(e)) {
10754
11200
  return e;
10755
11201
  }
@@ -10767,6 +11213,10 @@ function safeTransform(e, ctx) {
10767
11213
  dst.expr = dst.expr.key(e.index);
10768
11214
  return e.receiver;
10769
11215
  }
11216
+ if (e instanceof SafeInvokeFunctionExpr) {
11217
+ dst.expr = safeTernaryWithTemporary(dst.expr, (r) => r.callFn(e.args), ctx);
11218
+ return e.receiver;
11219
+ }
10770
11220
  if (e instanceof SafePropertyReadExpr) {
10771
11221
  dst.expr = safeTernaryWithTemporary(dst.expr, (r) => r.prop(e.name), ctx);
10772
11222
  return e.receiver;
@@ -10777,6 +11227,9 @@ function safeTransform(e, ctx) {
10777
11227
  }
10778
11228
  }
10779
11229
  else {
11230
+ if (e instanceof SafeInvokeFunctionExpr) {
11231
+ return safeTernaryWithTemporary(e.receiver, (r) => r.callFn(e.args), ctx);
11232
+ }
10780
11233
  if (e instanceof SafePropertyReadExpr) {
10781
11234
  return safeTernaryWithTemporary(e.receiver, (r) => r.prop(e.name), ctx);
10782
11235
  }
@@ -10834,7 +11287,7 @@ function phaseGenerateAdvance(cpl) {
10834
11287
  if (delta < 0) {
10835
11288
  throw new Error(`AssertionError: slot counter should never need to move backwards`);
10836
11289
  }
10837
- OpList.insertBefore(createAdvanceOp(delta), op);
11290
+ OpList.insertBefore(createAdvanceOp(delta, op.sourceSpan), op);
10838
11291
  slotContext = slot;
10839
11292
  }
10840
11293
  }
@@ -10872,7 +11325,7 @@ function recursivelyProcessView(view, parentScope) {
10872
11325
  switch (op.kind) {
10873
11326
  case OpKind.Template:
10874
11327
  // Descend into child embedded views.
10875
- recursivelyProcessView(view.tpl.views.get(op.xref), scope);
11328
+ recursivelyProcessView(view.job.views.get(op.xref), scope);
10876
11329
  break;
10877
11330
  case OpKind.Listener:
10878
11331
  // Prepend variables to listener handler functions.
@@ -10945,15 +11398,15 @@ function generateVariablesInScopeForView(view, scope) {
10945
11398
  // Before generating variables for a parent view, we need to switch to the context of the parent
10946
11399
  // view with a `nextContext` expression. This context switching operation itself declares a
10947
11400
  // variable, because the context of the view may be referenced directly.
10948
- newOps.push(createVariableOp(view.tpl.allocateXrefId(), scope.viewContextVariable, new NextContextExpr()));
11401
+ newOps.push(createVariableOp(view.job.allocateXrefId(), scope.viewContextVariable, new NextContextExpr()));
10949
11402
  }
10950
11403
  // Add variables for all context variables available in this scope's view.
10951
- for (const [name, value] of view.tpl.views.get(scope.view).contextVariables) {
10952
- newOps.push(createVariableOp(view.tpl.allocateXrefId(), scope.contextVariables.get(name), new ReadPropExpr(new ContextExpr(scope.view), value)));
11404
+ for (const [name, value] of view.job.views.get(scope.view).contextVariables) {
11405
+ newOps.push(createVariableOp(view.job.allocateXrefId(), scope.contextVariables.get(name), new ReadPropExpr(new ContextExpr(scope.view), value)));
10953
11406
  }
10954
11407
  // Add variables for all local references declared for elements in this scope.
10955
11408
  for (const ref of scope.references) {
10956
- newOps.push(createVariableOp(view.tpl.allocateXrefId(), ref.variable, new ReferenceExpr(ref.targetId, ref.offset)));
11409
+ newOps.push(createVariableOp(view.job.allocateXrefId(), ref.variable, new ReferenceExpr(ref.targetId, ref.offset)));
10957
11410
  }
10958
11411
  if (scope.parent !== null) {
10959
11412
  // Recursively add variables from the parent scope.
@@ -10962,6 +11415,62 @@ function generateVariablesInScopeForView(view, scope) {
10962
11415
  return newOps;
10963
11416
  }
10964
11417
 
11418
+ const STYLE_DOT = 'style.';
11419
+ const CLASS_DOT = 'class.';
11420
+ function phaseHostStylePropertyParsing(job) {
11421
+ for (const op of job.update) {
11422
+ if (op.kind !== OpKind.Binding) {
11423
+ continue;
11424
+ }
11425
+ if (op.name.startsWith(STYLE_DOT)) {
11426
+ op.bindingKind = BindingKind.StyleProperty;
11427
+ op.name = op.name.substring(STYLE_DOT.length);
11428
+ if (isCssCustomProperty$1(op.name)) {
11429
+ op.name = hyphenate(op.name);
11430
+ }
11431
+ const { property, suffix } = parseProperty$1(op.name);
11432
+ op.name = property;
11433
+ op.unit = suffix;
11434
+ }
11435
+ else if (op.name.startsWith('style!')) {
11436
+ // TODO: do we only transform !important?
11437
+ op.name = 'style';
11438
+ }
11439
+ else if (op.name.startsWith(CLASS_DOT)) {
11440
+ op.bindingKind = BindingKind.ClassName;
11441
+ op.name = parseProperty$1(op.name.substring(CLASS_DOT.length)).property;
11442
+ }
11443
+ }
11444
+ }
11445
+ /**
11446
+ * Checks whether property name is a custom CSS property.
11447
+ * See: https://www.w3.org/TR/css-variables-1
11448
+ */
11449
+ function isCssCustomProperty$1(name) {
11450
+ return name.startsWith('--');
11451
+ }
11452
+ function hyphenate(value) {
11453
+ return value
11454
+ .replace(/[a-z][A-Z]/g, v => {
11455
+ return v.charAt(0) + '-' + v.charAt(1);
11456
+ })
11457
+ .toLowerCase();
11458
+ }
11459
+ function parseProperty$1(name) {
11460
+ const overrideIndex = name.indexOf('!important');
11461
+ if (overrideIndex !== -1) {
11462
+ name = overrideIndex > 0 ? name.substring(0, overrideIndex) : '';
11463
+ }
11464
+ let suffix = null;
11465
+ let property = name;
11466
+ const unitIndex = name.lastIndexOf('.');
11467
+ if (unitIndex > 0) {
11468
+ suffix = name.slice(unitIndex + 1);
11469
+ property = name.substring(0, unitIndex);
11470
+ }
11471
+ return { property, suffix };
11472
+ }
11473
+
10965
11474
  /**
10966
11475
  * Lifts local reference declarations on element-like structures within each view into an entry in
10967
11476
  * the `consts` array for the whole component.
@@ -10998,82 +11507,62 @@ function serializeLocalRefs(refs) {
10998
11507
  }
10999
11508
 
11000
11509
  /**
11001
- * Parses string representation of a style and converts it into object literal.
11002
- *
11003
- * @param value string representation of style as used in the `style` attribute in HTML.
11004
- * Example: `color: red; height: auto`.
11005
- * @returns An array of style property name and value pairs, e.g. `['color', 'red', 'height',
11006
- * 'auto']`
11510
+ * Change namespaces between HTML, SVG and MathML, depending on the next element.
11007
11511
  */
11008
- function parse(value) {
11009
- // we use a string array here instead of a string map
11010
- // because a string-map is not guaranteed to retain the
11011
- // order of the entries whereas a string array can be
11012
- // constructed in a [key, value, key, value] format.
11013
- const styles = [];
11014
- let i = 0;
11015
- let parenDepth = 0;
11016
- let quote = 0 /* Char.QuoteNone */;
11017
- let valueStart = 0;
11018
- let propStart = 0;
11019
- let currentProp = null;
11020
- while (i < value.length) {
11021
- const token = value.charCodeAt(i++);
11022
- switch (token) {
11023
- case 40 /* Char.OpenParen */:
11024
- parenDepth++;
11025
- break;
11026
- case 41 /* Char.CloseParen */:
11027
- parenDepth--;
11028
- break;
11029
- case 39 /* Char.QuoteSingle */:
11030
- // valueStart needs to be there since prop values don't
11031
- // have quotes in CSS
11032
- if (quote === 0 /* Char.QuoteNone */) {
11033
- quote = 39 /* Char.QuoteSingle */;
11034
- }
11035
- else if (quote === 39 /* Char.QuoteSingle */ && value.charCodeAt(i - 1) !== 92 /* Char.BackSlash */) {
11036
- quote = 0 /* Char.QuoteNone */;
11037
- }
11038
- break;
11039
- case 34 /* Char.QuoteDouble */:
11040
- // same logic as above
11041
- if (quote === 0 /* Char.QuoteNone */) {
11042
- quote = 34 /* Char.QuoteDouble */;
11043
- }
11044
- else if (quote === 34 /* Char.QuoteDouble */ && value.charCodeAt(i - 1) !== 92 /* Char.BackSlash */) {
11045
- quote = 0 /* Char.QuoteNone */;
11046
- }
11047
- break;
11048
- case 58 /* Char.Colon */:
11049
- if (!currentProp && parenDepth === 0 && quote === 0 /* Char.QuoteNone */) {
11050
- currentProp = hyphenate(value.substring(propStart, i - 1).trim());
11051
- valueStart = i;
11052
- }
11053
- break;
11054
- case 59 /* Char.Semicolon */:
11055
- if (currentProp && valueStart > 0 && parenDepth === 0 && quote === 0 /* Char.QuoteNone */) {
11056
- const styleVal = value.substring(valueStart, i - 1).trim();
11057
- styles.push(currentProp, styleVal);
11058
- propStart = i;
11059
- valueStart = 0;
11060
- currentProp = null;
11061
- }
11062
- break;
11512
+ function phaseNamespace(job) {
11513
+ for (const [_, view] of job.views) {
11514
+ let activeNamespace = Namespace.HTML;
11515
+ for (const op of view.create) {
11516
+ if (op.kind !== OpKind.Element && op.kind !== OpKind.ElementStart) {
11517
+ continue;
11518
+ }
11519
+ if (op.namespace !== activeNamespace) {
11520
+ OpList.insertBefore(createNamespaceOp(op.namespace), op);
11521
+ activeNamespace = op.namespace;
11522
+ }
11063
11523
  }
11064
11524
  }
11065
- if (currentProp && valueStart) {
11066
- const styleVal = value.slice(valueStart).trim();
11067
- styles.push(currentProp, styleVal);
11525
+ }
11526
+
11527
+ const BINARY_OPERATORS = new Map([
11528
+ ['&&', BinaryOperator.And],
11529
+ ['>', BinaryOperator.Bigger],
11530
+ ['>=', BinaryOperator.BiggerEquals],
11531
+ ['&', BinaryOperator.BitwiseAnd],
11532
+ ['/', BinaryOperator.Divide],
11533
+ ['==', BinaryOperator.Equals],
11534
+ ['===', BinaryOperator.Identical],
11535
+ ['<', BinaryOperator.Lower],
11536
+ ['<=', BinaryOperator.LowerEquals],
11537
+ ['-', BinaryOperator.Minus],
11538
+ ['%', BinaryOperator.Modulo],
11539
+ ['*', BinaryOperator.Multiply],
11540
+ ['!=', BinaryOperator.NotEquals],
11541
+ ['!==', BinaryOperator.NotIdentical],
11542
+ ['??', BinaryOperator.NullishCoalesce],
11543
+ ['||', BinaryOperator.Or],
11544
+ ['+', BinaryOperator.Plus],
11545
+ ]);
11546
+ const NAMESPACES = new Map([['svg', Namespace.SVG], ['math', Namespace.Math]]);
11547
+ function namespaceForKey(namespacePrefixKey) {
11548
+ if (namespacePrefixKey === null) {
11549
+ return Namespace.HTML;
11068
11550
  }
11069
- return styles;
11551
+ return NAMESPACES.get(namespacePrefixKey) ?? Namespace.HTML;
11070
11552
  }
11071
- function hyphenate(value) {
11072
- return value
11073
- .replace(/[a-z][A-Z]/g, v => {
11074
- return v.charAt(0) + '-' + v.charAt(1);
11075
- })
11076
- .toLowerCase();
11553
+ function keyForNamespace(namespace) {
11554
+ for (const [k, n] of NAMESPACES.entries()) {
11555
+ if (n === namespace) {
11556
+ return k;
11557
+ }
11558
+ }
11559
+ return null; // No namespace prefix for HTML
11560
+ }
11561
+ function prefixWithNamespace(strippedTag, namespace) {
11562
+ if (namespace === Namespace.HTML) {
11563
+ return strippedTag;
11564
+ }
11565
+ return `:${keyForNamespace(namespace)}:${strippedTag}`;
11077
11566
  }
11078
11567
 
11079
11568
  /**
@@ -11082,41 +11571,53 @@ function hyphenate(value) {
11082
11571
  * This includes propagating those names into any `ir.ReadVariableExpr`s of those variables, so that
11083
11572
  * the reads can be emitted correctly.
11084
11573
  */
11085
- function phaseNaming(cpl, compatibility) {
11086
- addNamesToView(cpl.root, cpl.componentName, { index: 0 }, compatibility);
11574
+ function phaseNaming(cpl) {
11575
+ addNamesToView(cpl.root, cpl.componentName, { index: 0 }, cpl.compatibility === CompatibilityMode.TemplateDefinitionBuilder);
11087
11576
  }
11088
- function addNamesToView(view, baseName, state, compatibility) {
11089
- if (view.fnName === null) {
11090
- view.fnName = sanitizeIdentifier(`${baseName}_Template`);
11577
+ function addNamesToView(unit, baseName, state, compatibility) {
11578
+ if (unit.fnName === null) {
11579
+ unit.fnName = sanitizeIdentifier(`${baseName}_${unit.job.fnSuffix}`);
11091
11580
  }
11092
11581
  // Keep track of the names we assign to variables in the view. We'll need to propagate these
11093
11582
  // into reads of those variables afterwards.
11094
11583
  const varNames = new Map();
11095
- for (const op of view.ops()) {
11584
+ for (const op of unit.ops()) {
11096
11585
  switch (op.kind) {
11586
+ case OpKind.Property:
11587
+ if (op.isAnimationTrigger) {
11588
+ op.name = '@' + op.name;
11589
+ }
11590
+ break;
11097
11591
  case OpKind.Listener:
11098
11592
  if (op.handlerFnName === null) {
11099
- // TODO(alxhub): convert this temporary name to match how the
11100
- // `TemplateDefinitionBuilder` names listener functions.
11101
11593
  if (op.slot === null) {
11102
11594
  throw new Error(`Expected a slot to be assigned`);
11103
11595
  }
11104
- op.handlerFnName =
11105
- sanitizeIdentifier(`${view.fnName}_${op.tag}_${op.name}_${op.slot}_listener`);
11596
+ const safeTagName = op.tag.replace('-', '_');
11597
+ if (op.isAnimationListener) {
11598
+ op.handlerFnName = sanitizeIdentifier(`${unit.fnName}_${safeTagName}_animation_${op.name}_${op.animationPhase}_${op.slot}_listener`);
11599
+ op.name = `@${op.name}.${op.animationPhase}`;
11600
+ }
11601
+ else {
11602
+ op.handlerFnName =
11603
+ sanitizeIdentifier(`${unit.fnName}_${safeTagName}_${op.name}_${op.slot}_listener`);
11604
+ }
11106
11605
  }
11107
11606
  break;
11108
11607
  case OpKind.Variable:
11109
11608
  varNames.set(op.xref, getVariableName(op.variable, state));
11110
11609
  break;
11111
11610
  case OpKind.Template:
11112
- const childView = view.tpl.views.get(op.xref);
11611
+ if (!(unit instanceof ViewCompilationUnit)) {
11612
+ throw new Error(`AssertionError: must be compiling a component`);
11613
+ }
11614
+ const childView = unit.job.views.get(op.xref);
11113
11615
  if (op.slot === null) {
11114
11616
  throw new Error(`Expected slot to be assigned`);
11115
11617
  }
11116
- addNamesToView(childView, `${baseName}_${op.tag}_${op.slot}`, state, compatibility);
11618
+ addNamesToView(childView, `${baseName}_${prefixWithNamespace(op.tag, op.namespace)}_${op.slot}`, state, compatibility);
11117
11619
  break;
11118
11620
  case OpKind.StyleProp:
11119
- case OpKind.InterpolateStyleProp:
11120
11621
  op.name = normalizeStylePropName(op.name);
11121
11622
  if (compatibility) {
11122
11623
  op.name = stripImportant(op.name);
@@ -11131,7 +11632,7 @@ function addNamesToView(view, baseName, state, compatibility) {
11131
11632
  }
11132
11633
  // Having named all variables declared in the view, now we can push those names into the
11133
11634
  // `ir.ReadVariableExpr` expressions which represent reads of those variables.
11134
- for (const op of view.ops()) {
11635
+ for (const op of unit.ops()) {
11135
11636
  visitExpressionsInOp(op, expr => {
11136
11637
  if (!(expr instanceof ReadVariableExpr) || expr.name !== null) {
11137
11638
  return;
@@ -11146,6 +11647,9 @@ function addNamesToView(view, baseName, state, compatibility) {
11146
11647
  function getVariableName(variable, state) {
11147
11648
  if (variable.name === null) {
11148
11649
  switch (variable.kind) {
11650
+ case SemanticVariableKind.Context:
11651
+ variable.name = `ctx_r${state.index++}`;
11652
+ break;
11149
11653
  case SemanticVariableKind.Identifier:
11150
11654
  variable.name = `${variable.identifier}_${state.index++}`;
11151
11655
  break;
@@ -11160,7 +11664,7 @@ function getVariableName(variable, state) {
11160
11664
  * Normalizes a style prop name by hyphenating it (unless its a CSS variable).
11161
11665
  */
11162
11666
  function normalizeStylePropName(name) {
11163
- return name.startsWith('--') ? name : hyphenate(name);
11667
+ return name.startsWith('--') ? name : hyphenate$1(name);
11164
11668
  }
11165
11669
  /**
11166
11670
  * Strips `!important` out of the given style or class name.
@@ -11257,15 +11761,82 @@ function phaseNgContainer(cpl) {
11257
11761
  }
11258
11762
  }
11259
11763
 
11260
- function phaseNullishCoalescing(cpl) {
11261
- for (const view of cpl.views.values()) {
11262
- for (const op of view.ops()) {
11764
+ /**
11765
+ * Transforms special-case bindings with 'style' or 'class' in their names. Must run before the
11766
+ * main binding specialization pass.
11767
+ */
11768
+ function phaseNoListenersOnTemplates(job) {
11769
+ for (const unit of job.units) {
11770
+ let inTemplate = false;
11771
+ for (const op of unit.create) {
11772
+ switch (op.kind) {
11773
+ case OpKind.Template:
11774
+ inTemplate = true;
11775
+ break;
11776
+ case OpKind.ElementStart:
11777
+ case OpKind.Element:
11778
+ case OpKind.ContainerStart:
11779
+ case OpKind.Container:
11780
+ inTemplate = false;
11781
+ break;
11782
+ case OpKind.Listener:
11783
+ if (inTemplate) {
11784
+ OpList.remove(op);
11785
+ }
11786
+ break;
11787
+ }
11788
+ }
11789
+ }
11790
+ }
11791
+
11792
+ /**
11793
+ * Looks up an element in the given map by xref ID.
11794
+ */
11795
+ function lookupElement(elements, xref) {
11796
+ const el = elements.get(xref);
11797
+ if (el === undefined) {
11798
+ throw new Error('All attributes should have an element-like target.');
11799
+ }
11800
+ return el;
11801
+ }
11802
+ /**
11803
+ * When a container is marked with `ngNonBindable`, the non-bindable characteristic also applies to
11804
+ * all descendants of that container. Therefore, we must emit `disableBindings` and `enableBindings`
11805
+ * instructions for every such container.
11806
+ */
11807
+ function phaseNonbindable(job) {
11808
+ const elements = new Map();
11809
+ for (const view of job.units) {
11810
+ for (const op of view.create) {
11811
+ if (!isElementOrContainerOp(op)) {
11812
+ continue;
11813
+ }
11814
+ elements.set(op.xref, op);
11815
+ }
11816
+ }
11817
+ for (const [_, view] of job.views) {
11818
+ for (const op of view.create) {
11819
+ if ((op.kind === OpKind.ElementStart || op.kind === OpKind.ContainerStart) &&
11820
+ op.nonBindable) {
11821
+ OpList.insertAfter(createDisableBindingsOp(op.xref), op);
11822
+ }
11823
+ if ((op.kind === OpKind.ElementEnd || op.kind === OpKind.ContainerEnd) &&
11824
+ lookupElement(elements, op.xref).nonBindable) {
11825
+ OpList.insertBefore(createEnableBindingsOp(op.xref), op);
11826
+ }
11827
+ }
11828
+ }
11829
+ }
11830
+
11831
+ function phaseNullishCoalescing(job) {
11832
+ for (const unit of job.units) {
11833
+ for (const op of unit.ops()) {
11263
11834
  transformExpressionsInOp(op, expr => {
11264
11835
  if (!(expr instanceof BinaryOperatorExpr) ||
11265
11836
  expr.operator !== BinaryOperator.NullishCoalesce) {
11266
11837
  return expr;
11267
11838
  }
11268
- const assignment = new AssignTemporaryExpr(expr.lhs.clone(), cpl.allocateXrefId());
11839
+ const assignment = new AssignTemporaryExpr(expr.lhs.clone(), job.allocateXrefId());
11269
11840
  const read = new ReadTemporaryExpr(assignment.xref);
11270
11841
  // TODO: When not in compatibility mode for TemplateDefinitionBuilder, we can just emit
11271
11842
  // `t != null` instead of including an undefined check as well.
@@ -11341,23 +11912,40 @@ function phasePipeVariadic(cpl) {
11341
11912
  }
11342
11913
  }
11343
11914
 
11915
+ function kindTest(kind) {
11916
+ return (op) => op.kind === kind;
11917
+ }
11344
11918
  /**
11345
11919
  * Defines the groups based on `OpKind` that ops will be divided into. Ops will be collected into
11346
11920
  * groups, then optionally transformed, before recombining the groups in the order defined here.
11347
11921
  */
11348
11922
  const ORDERING = [
11349
- { kinds: new Set([OpKind.StyleMap, OpKind.InterpolateStyleMap]), transform: keepLast },
11350
- { kinds: new Set([OpKind.ClassMap, OpKind.InterpolateClassMap]), transform: keepLast },
11351
- { kinds: new Set([OpKind.StyleProp, OpKind.InterpolateStyleProp]) },
11352
- { kinds: new Set([OpKind.ClassProp]) },
11353
- { kinds: new Set([OpKind.InterpolateProperty]) },
11354
- { kinds: new Set([OpKind.Property]) },
11355
- { kinds: new Set([OpKind.Attribute, OpKind.InterpolateAttribute]) },
11923
+ { test: kindTest(OpKind.StyleMap), transform: keepLast },
11924
+ { test: kindTest(OpKind.ClassMap), transform: keepLast },
11925
+ { test: kindTest(OpKind.StyleProp) },
11926
+ { test: kindTest(OpKind.ClassProp) },
11927
+ {
11928
+ test: (op) => (op.kind === OpKind.Property || op.kind === OpKind.HostProperty) &&
11929
+ op.expression instanceof Interpolation
11930
+ },
11931
+ {
11932
+ test: (op) => (op.kind === OpKind.Property || op.kind === OpKind.HostProperty) &&
11933
+ !(op.expression instanceof Interpolation)
11934
+ },
11935
+ { test: kindTest(OpKind.Attribute) },
11356
11936
  ];
11357
11937
  /**
11358
11938
  * The set of all op kinds we handle in the reordering phase.
11359
11939
  */
11360
- const handledOpKinds = new Set(ORDERING.flatMap(group => [...group.kinds]));
11940
+ const handledOpKinds = new Set([
11941
+ OpKind.StyleMap,
11942
+ OpKind.ClassMap,
11943
+ OpKind.StyleProp,
11944
+ OpKind.ClassProp,
11945
+ OpKind.Property,
11946
+ OpKind.HostProperty,
11947
+ OpKind.Attribute,
11948
+ ]);
11361
11949
  /**
11362
11950
  * Reorders property and attribute ops according to the following ordering:
11363
11951
  * 1. styleMap & styleMapInterpolate (drops all but the last op in the group)
@@ -11369,9 +11957,9 @@ const handledOpKinds = new Set(ORDERING.flatMap(group => [...group.kinds]));
11369
11957
  * 7. attribute & attributeInterpolate (ordering preserve within group)
11370
11958
  */
11371
11959
  function phasePropertyOrdering(cpl) {
11372
- for (const [_, view] of cpl.views) {
11960
+ for (const unit of cpl.units) {
11373
11961
  let opsToOrder = [];
11374
- for (const op of view.update) {
11962
+ for (const op of unit.update) {
11375
11963
  if (handledOpKinds.has(op.kind)) {
11376
11964
  // Pull out ops that need o be ordered.
11377
11965
  opsToOrder.push(op);
@@ -11388,7 +11976,7 @@ function phasePropertyOrdering(cpl) {
11388
11976
  }
11389
11977
  // If we still have ops pulled at the end, put them back in the correct order.
11390
11978
  for (const orderedOp of reorder(opsToOrder)) {
11391
- view.update.push(orderedOp);
11979
+ unit.update.push(orderedOp);
11392
11980
  }
11393
11981
  }
11394
11982
  }
@@ -11399,7 +11987,7 @@ function reorder(ops) {
11399
11987
  // Break the ops list into groups based on OpKind.
11400
11988
  const groups = Array.from(ORDERING, () => new Array());
11401
11989
  for (const op of ops) {
11402
- const groupIndex = ORDERING.findIndex(o => o.kinds.has(op.kind));
11990
+ const groupIndex = ORDERING.findIndex(o => o.test(op));
11403
11991
  groups[groupIndex].push(op);
11404
11992
  }
11405
11993
  // Reassemble the groups into a single list, in the correct order.
@@ -11415,15 +12003,15 @@ function keepLast(ops) {
11415
12003
  return ops.slice(ops.length - 1);
11416
12004
  }
11417
12005
 
11418
- function phasePureFunctionExtraction(cpl) {
11419
- for (const view of cpl.views.values()) {
12006
+ function phasePureFunctionExtraction(job) {
12007
+ for (const view of job.units) {
11420
12008
  for (const op of view.ops()) {
11421
12009
  visitExpressionsInOp(op, expr => {
11422
12010
  if (!(expr instanceof PureFunctionExpr) || expr.body === null) {
11423
12011
  return;
11424
12012
  }
11425
12013
  const constantDef = new PureFunctionConstant(expr.args.length);
11426
- expr.fn = cpl.pool.getSharedConstant(constantDef, expr.body);
12014
+ expr.fn = job.pool.getSharedConstant(constantDef, expr.body);
11427
12015
  expr.body = null;
11428
12016
  });
11429
12017
  }
@@ -11459,8 +12047,8 @@ class PureFunctionConstant extends GenericKeyFn {
11459
12047
  }
11460
12048
  }
11461
12049
 
11462
- function phasePureLiteralStructures(cpl) {
11463
- for (const view of cpl.views.values()) {
12050
+ function phasePureLiteralStructures(job) {
12051
+ for (const view of job.units) {
11464
12052
  for (const op of view.update) {
11465
12053
  transformExpressionsInOp(op, (expr, flags) => {
11466
12054
  if (flags & VisitorContextFlag.InChildOperation) {
@@ -11511,13 +12099,13 @@ function transformLiteralMap(expr) {
11511
12099
  // This file contains helpers for generating calls to Ivy instructions. In particular, each
11512
12100
  // instruction type is represented as a function, which may select a specific instruction variant
11513
12101
  // depending on the exact arguments.
11514
- function element(slot, tag, constIndex, localRefIndex) {
11515
- return elementOrContainerBase(Identifiers.element, slot, tag, constIndex, localRefIndex);
12102
+ function element(slot, tag, constIndex, localRefIndex, sourceSpan) {
12103
+ return elementOrContainerBase(Identifiers.element, slot, tag, constIndex, localRefIndex, sourceSpan);
11516
12104
  }
11517
- function elementStart(slot, tag, constIndex, localRefIndex) {
11518
- return elementOrContainerBase(Identifiers.elementStart, slot, tag, constIndex, localRefIndex);
12105
+ function elementStart(slot, tag, constIndex, localRefIndex, sourceSpan) {
12106
+ return elementOrContainerBase(Identifiers.elementStart, slot, tag, constIndex, localRefIndex, sourceSpan);
11519
12107
  }
11520
- function elementOrContainerBase(instruction, slot, tag, constIndex, localRefIndex) {
12108
+ function elementOrContainerBase(instruction, slot, tag, constIndex, localRefIndex, sourceSpan) {
11521
12109
  const args = [literal(slot)];
11522
12110
  if (tag !== null) {
11523
12111
  args.push(literal(tag));
@@ -11529,21 +12117,21 @@ function elementOrContainerBase(instruction, slot, tag, constIndex, localRefInde
11529
12117
  else if (constIndex !== null) {
11530
12118
  args.push(literal(constIndex));
11531
12119
  }
11532
- return call(instruction, args);
12120
+ return call(instruction, args, sourceSpan);
11533
12121
  }
11534
- function elementEnd() {
11535
- return call(Identifiers.elementEnd, []);
12122
+ function elementEnd(sourceSpan) {
12123
+ return call(Identifiers.elementEnd, [], sourceSpan);
11536
12124
  }
11537
- function elementContainerStart(slot, constIndex, localRefIndex) {
11538
- return elementOrContainerBase(Identifiers.elementContainerStart, slot, /* tag */ null, constIndex, localRefIndex);
12125
+ function elementContainerStart(slot, constIndex, localRefIndex, sourceSpan) {
12126
+ return elementOrContainerBase(Identifiers.elementContainerStart, slot, /* tag */ null, constIndex, localRefIndex, sourceSpan);
11539
12127
  }
11540
- function elementContainer(slot, constIndex, localRefIndex) {
11541
- return elementOrContainerBase(Identifiers.elementContainer, slot, /* tag */ null, constIndex, localRefIndex);
12128
+ function elementContainer(slot, constIndex, localRefIndex, sourceSpan) {
12129
+ return elementOrContainerBase(Identifiers.elementContainer, slot, /* tag */ null, constIndex, localRefIndex, sourceSpan);
11542
12130
  }
11543
12131
  function elementContainerEnd() {
11544
- return call(Identifiers.elementContainerEnd, []);
12132
+ return call(Identifiers.elementContainerEnd, [], null);
11545
12133
  }
11546
- function template(slot, templateFnRef, decls, vars, tag, constIndex) {
12134
+ function template(slot, templateFnRef, decls, vars, tag, constIndex, sourceSpan) {
11547
12135
  return call(Identifiers.templateCreate, [
11548
12136
  literal(slot),
11549
12137
  templateFnRef,
@@ -11551,24 +12139,39 @@ function template(slot, templateFnRef, decls, vars, tag, constIndex) {
11551
12139
  literal(vars),
11552
12140
  literal(tag),
11553
12141
  literal(constIndex),
11554
- ]);
12142
+ ], sourceSpan);
12143
+ }
12144
+ function disableBindings() {
12145
+ return call(Identifiers.disableBindings, [], null);
12146
+ }
12147
+ function enableBindings() {
12148
+ return call(Identifiers.enableBindings, [], null);
11555
12149
  }
11556
12150
  function listener(name, handlerFn) {
11557
12151
  return call(Identifiers.listener, [
11558
12152
  literal(name),
11559
12153
  handlerFn,
11560
- ]);
12154
+ ], null);
11561
12155
  }
11562
12156
  function pipe(slot, name) {
11563
12157
  return call(Identifiers.pipe, [
11564
12158
  literal(slot),
11565
12159
  literal(name),
11566
- ]);
12160
+ ], null);
12161
+ }
12162
+ function namespaceHTML() {
12163
+ return call(Identifiers.namespaceHTML, [], null);
12164
+ }
12165
+ function namespaceSVG() {
12166
+ return call(Identifiers.namespaceSVG, [], null);
11567
12167
  }
11568
- function advance(delta) {
12168
+ function namespaceMath() {
12169
+ return call(Identifiers.namespaceMathML, [], null);
12170
+ }
12171
+ function advance(delta, sourceSpan) {
11569
12172
  return call(Identifiers.advance, [
11570
12173
  literal(delta),
11571
- ]);
12174
+ ], sourceSpan);
11572
12175
  }
11573
12176
  function reference(slot) {
11574
12177
  return importExpr(Identifiers.reference).callFn([
@@ -11591,37 +12194,42 @@ function resetView(returnValue) {
11591
12194
  returnValue,
11592
12195
  ]);
11593
12196
  }
11594
- function text(slot, initialValue) {
11595
- const args = [literal(slot)];
12197
+ function text(slot, initialValue, sourceSpan) {
12198
+ const args = [literal(slot, null)];
11596
12199
  if (initialValue !== '') {
11597
12200
  args.push(literal(initialValue));
11598
12201
  }
11599
- return call(Identifiers.text, args);
12202
+ return call(Identifiers.text, args, sourceSpan);
11600
12203
  }
11601
- function property(name, expression) {
11602
- return call(Identifiers.property, [
11603
- literal(name),
11604
- expression,
11605
- ]);
12204
+ function property(name, expression, sanitizer, sourceSpan) {
12205
+ const args = [literal(name), expression];
12206
+ if (sanitizer !== null) {
12207
+ args.push(sanitizer);
12208
+ }
12209
+ return call(Identifiers.property, args, sourceSpan);
11606
12210
  }
11607
- function attribute(name, expression) {
11608
- return call(Identifiers.attribute, [literal(name), expression]);
12211
+ function attribute(name, expression, sanitizer) {
12212
+ const args = [literal(name), expression];
12213
+ if (sanitizer !== null) {
12214
+ args.push(sanitizer);
12215
+ }
12216
+ return call(Identifiers.attribute, args, null);
11609
12217
  }
11610
12218
  function styleProp(name, expression, unit) {
11611
12219
  const args = [literal(name), expression];
11612
12220
  if (unit !== null) {
11613
12221
  args.push(literal(unit));
11614
12222
  }
11615
- return call(Identifiers.styleProp, args);
12223
+ return call(Identifiers.styleProp, args, null);
11616
12224
  }
11617
12225
  function classProp(name, expression) {
11618
- return call(Identifiers.classProp, [literal(name), expression]);
12226
+ return call(Identifiers.classProp, [literal(name), expression], null);
11619
12227
  }
11620
12228
  function styleMap(expression) {
11621
- return call(Identifiers.styleMap, [expression]);
12229
+ return call(Identifiers.styleMap, [expression], null);
11622
12230
  }
11623
12231
  function classMap(expression) {
11624
- return call(Identifiers.classMap, [expression]);
12232
+ return call(Identifiers.classMap, [expression], null);
11625
12233
  }
11626
12234
  const PIPE_BINDINGS = [
11627
12235
  Identifiers.pipeBind1,
@@ -11647,7 +12255,7 @@ function pipeBindV(slot, varOffset, args) {
11647
12255
  args,
11648
12256
  ]);
11649
12257
  }
11650
- function textInterpolate(strings, expressions) {
12258
+ function textInterpolate(strings, expressions, sourceSpan) {
11651
12259
  if (strings.length < 1 || expressions.length !== strings.length - 1) {
11652
12260
  throw new Error(`AssertionError: expected specific shape of args for strings/expressions in interpolation`);
11653
12261
  }
@@ -11663,15 +12271,23 @@ function textInterpolate(strings, expressions) {
11663
12271
  // idx points at the last string.
11664
12272
  interpolationArgs.push(literal(strings[idx]));
11665
12273
  }
11666
- return callVariadicInstruction(TEXT_INTERPOLATE_CONFIG, [], interpolationArgs);
12274
+ return callVariadicInstruction(TEXT_INTERPOLATE_CONFIG, [], interpolationArgs, [], sourceSpan);
11667
12275
  }
11668
- function propertyInterpolate(name, strings, expressions) {
12276
+ function propertyInterpolate(name, strings, expressions, sanitizer, sourceSpan) {
11669
12277
  const interpolationArgs = collateInterpolationArgs(strings, expressions);
11670
- return callVariadicInstruction(PROPERTY_INTERPOLATE_CONFIG, [literal(name)], interpolationArgs);
12278
+ const extraArgs = [];
12279
+ if (sanitizer !== null) {
12280
+ extraArgs.push(sanitizer);
12281
+ }
12282
+ return callVariadicInstruction(PROPERTY_INTERPOLATE_CONFIG, [literal(name)], interpolationArgs, extraArgs, sourceSpan);
11671
12283
  }
11672
- function attributeInterpolate(name, strings, expressions) {
12284
+ function attributeInterpolate(name, strings, expressions, sanitizer) {
11673
12285
  const interpolationArgs = collateInterpolationArgs(strings, expressions);
11674
- return callVariadicInstruction(ATTRIBUTE_INTERPOLATE_CONFIG, [literal(name)], interpolationArgs);
12286
+ const extraArgs = [];
12287
+ if (sanitizer !== null) {
12288
+ extraArgs.push(sanitizer);
12289
+ }
12290
+ return callVariadicInstruction(ATTRIBUTE_INTERPOLATE_CONFIG, [literal(name)], interpolationArgs, extraArgs, null);
11675
12291
  }
11676
12292
  function stylePropInterpolate(name, strings, expressions, unit) {
11677
12293
  const interpolationArgs = collateInterpolationArgs(strings, expressions);
@@ -11679,21 +12295,24 @@ function stylePropInterpolate(name, strings, expressions, unit) {
11679
12295
  if (unit !== null) {
11680
12296
  extraArgs.push(literal(unit));
11681
12297
  }
11682
- return callVariadicInstruction(STYLE_PROP_INTERPOLATE_CONFIG, [literal(name)], interpolationArgs, extraArgs);
12298
+ return callVariadicInstruction(STYLE_PROP_INTERPOLATE_CONFIG, [literal(name)], interpolationArgs, extraArgs, null);
11683
12299
  }
11684
12300
  function styleMapInterpolate(strings, expressions) {
11685
12301
  const interpolationArgs = collateInterpolationArgs(strings, expressions);
11686
- return callVariadicInstruction(STYLE_MAP_INTERPOLATE_CONFIG, [], interpolationArgs);
12302
+ return callVariadicInstruction(STYLE_MAP_INTERPOLATE_CONFIG, [], interpolationArgs, [], null);
11687
12303
  }
11688
12304
  function classMapInterpolate(strings, expressions) {
11689
12305
  const interpolationArgs = collateInterpolationArgs(strings, expressions);
11690
- return callVariadicInstruction(CLASS_MAP_INTERPOLATE_CONFIG, [], interpolationArgs);
12306
+ return callVariadicInstruction(CLASS_MAP_INTERPOLATE_CONFIG, [], interpolationArgs, [], null);
12307
+ }
12308
+ function hostProperty(name, expression) {
12309
+ return call(Identifiers.hostProperty, [literal(name), expression], null);
11691
12310
  }
11692
12311
  function pureFunction(varOffset, fn, args) {
11693
12312
  return callVariadicInstructionExpr(PURE_FUNCTION_CONFIG, [
11694
12313
  literal(varOffset),
11695
12314
  fn,
11696
- ], args);
12315
+ ], args, [], null);
11697
12316
  }
11698
12317
  /**
11699
12318
  * Collates the string an expression arguments for an interpolation instruction.
@@ -11716,8 +12335,9 @@ function collateInterpolationArgs(strings, expressions) {
11716
12335
  }
11717
12336
  return interpolationArgs;
11718
12337
  }
11719
- function call(instruction, args) {
11720
- return createStatementOp(importExpr(instruction).callFn(args).toStmt());
12338
+ function call(instruction, args, sourceSpan) {
12339
+ const expr = importExpr(instruction).callFn(args, sourceSpan);
12340
+ return createStatementOp(new ExpressionStatement(expr, sourceSpan));
11721
12341
  }
11722
12342
  /**
11723
12343
  * `InterpolationConfig` for the `textInterpolate` instruction.
@@ -11872,28 +12492,37 @@ const PURE_FUNCTION_CONFIG = {
11872
12492
  variable: Identifiers.pureFunctionV,
11873
12493
  mapping: n => n,
11874
12494
  };
11875
- function callVariadicInstructionExpr(config, baseArgs, interpolationArgs, extraArgs = []) {
12495
+ function callVariadicInstructionExpr(config, baseArgs, interpolationArgs, extraArgs, sourceSpan) {
11876
12496
  const n = config.mapping(interpolationArgs.length);
11877
12497
  if (n < config.constant.length) {
11878
12498
  // Constant calling pattern.
11879
- return importExpr(config.constant[n]).callFn([
11880
- ...baseArgs, ...interpolationArgs, ...extraArgs
11881
- ]);
12499
+ return importExpr(config.constant[n])
12500
+ .callFn([...baseArgs, ...interpolationArgs, ...extraArgs], sourceSpan);
11882
12501
  }
11883
12502
  else if (config.variable !== null) {
11884
12503
  // Variable calling pattern.
11885
- return importExpr(config.variable).callFn([
11886
- ...baseArgs, literalArr(interpolationArgs), ...extraArgs
11887
- ]);
12504
+ return importExpr(config.variable)
12505
+ .callFn([...baseArgs, literalArr(interpolationArgs), ...extraArgs], sourceSpan);
11888
12506
  }
11889
12507
  else {
11890
12508
  throw new Error(`AssertionError: unable to call variadic function`);
11891
12509
  }
11892
12510
  }
11893
- function callVariadicInstruction(config, baseArgs, interpolationArgs, extraArgs = []) {
11894
- return createStatementOp(callVariadicInstructionExpr(config, baseArgs, interpolationArgs, extraArgs).toStmt());
12511
+ function callVariadicInstruction(config, baseArgs, interpolationArgs, extraArgs, sourceSpan) {
12512
+ return createStatementOp(callVariadicInstructionExpr(config, baseArgs, interpolationArgs, extraArgs, sourceSpan)
12513
+ .toStmt());
11895
12514
  }
11896
12515
 
12516
+ /**
12517
+ * Map of sanitizers to their identifier.
12518
+ */
12519
+ const sanitizerIdentifierMap = new Map([
12520
+ [SanitizerFn.Html, Identifiers.sanitizeHtml],
12521
+ [SanitizerFn.IframeAttribute, Identifiers.validateIframeAttribute],
12522
+ [SanitizerFn.ResourceUrl, Identifiers.sanitizeResourceUrl],
12523
+ [SanitizerFn.Script, Identifiers.sanitizeScript],
12524
+ [SanitizerFn.Style, Identifiers.sanitizeStyle], [SanitizerFn.Url, Identifiers.sanitizeUrl]
12525
+ ]);
11897
12526
  /**
11898
12527
  * Compiles semantic operations across all views and generates output `o.Statement`s with actual
11899
12528
  * runtime calls in their place.
@@ -11903,45 +12532,54 @@ function callVariadicInstruction(config, baseArgs, interpolationArgs, extraArgs
11903
12532
  * `ir.StatementOp`s (which wrap generated `o.Statement`s).
11904
12533
  */
11905
12534
  function phaseReify(cpl) {
11906
- for (const [_, view] of cpl.views) {
11907
- reifyCreateOperations(view, view.create);
11908
- reifyUpdateOperations(view, view.update);
12535
+ for (const unit of cpl.units) {
12536
+ reifyCreateOperations(unit, unit.create);
12537
+ reifyUpdateOperations(unit, unit.update);
11909
12538
  }
11910
12539
  }
11911
- function reifyCreateOperations(view, ops) {
12540
+ function reifyCreateOperations(unit, ops) {
11912
12541
  for (const op of ops) {
11913
12542
  transformExpressionsInOp(op, reifyIrExpression, VisitorContextFlag.None);
11914
12543
  switch (op.kind) {
11915
12544
  case OpKind.Text:
11916
- OpList.replace(op, text(op.slot, op.initialValue));
12545
+ OpList.replace(op, text(op.slot, op.initialValue, op.sourceSpan));
11917
12546
  break;
11918
12547
  case OpKind.ElementStart:
11919
- OpList.replace(op, elementStart(op.slot, op.tag, op.attributes, op.localRefs));
12548
+ OpList.replace(op, elementStart(op.slot, op.tag, op.attributes, op.localRefs, op.sourceSpan));
11920
12549
  break;
11921
12550
  case OpKind.Element:
11922
- OpList.replace(op, element(op.slot, op.tag, op.attributes, op.localRefs));
12551
+ OpList.replace(op, element(op.slot, op.tag, op.attributes, op.localRefs, op.sourceSpan));
11923
12552
  break;
11924
12553
  case OpKind.ElementEnd:
11925
- OpList.replace(op, elementEnd());
12554
+ OpList.replace(op, elementEnd(op.sourceSpan));
11926
12555
  break;
11927
12556
  case OpKind.ContainerStart:
11928
- OpList.replace(op, elementContainerStart(op.slot, op.attributes, op.localRefs));
12557
+ OpList.replace(op, elementContainerStart(op.slot, op.attributes, op.localRefs, op.sourceSpan));
11929
12558
  break;
11930
12559
  case OpKind.Container:
11931
- OpList.replace(op, elementContainer(op.slot, op.attributes, op.localRefs));
12560
+ OpList.replace(op, elementContainer(op.slot, op.attributes, op.localRefs, op.sourceSpan));
11932
12561
  break;
11933
12562
  case OpKind.ContainerEnd:
11934
12563
  OpList.replace(op, elementContainerEnd());
11935
12564
  break;
11936
12565
  case OpKind.Template:
11937
- const childView = view.tpl.views.get(op.xref);
11938
- OpList.replace(op, template(op.slot, variable(childView.fnName), childView.decls, childView.vars, op.tag, op.attributes));
12566
+ if (!(unit instanceof ViewCompilationUnit)) {
12567
+ throw new Error(`AssertionError: must be compiling a component`);
12568
+ }
12569
+ const childView = unit.job.views.get(op.xref);
12570
+ OpList.replace(op, template(op.slot, variable(childView.fnName), childView.decls, childView.vars, op.tag, op.attributes, op.sourceSpan));
12571
+ break;
12572
+ case OpKind.DisableBindings:
12573
+ OpList.replace(op, disableBindings());
12574
+ break;
12575
+ case OpKind.EnableBindings:
12576
+ OpList.replace(op, enableBindings());
11939
12577
  break;
11940
12578
  case OpKind.Pipe:
11941
12579
  OpList.replace(op, pipe(op.slot, op.name));
11942
12580
  break;
11943
12581
  case OpKind.Listener:
11944
- const listenerFn = reifyListenerHandler(view, op.handlerFnName, op.handlerOps);
12582
+ const listenerFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, op.consumesDollarEvent);
11945
12583
  OpList.replace(op, listener(op.name, listenerFn));
11946
12584
  break;
11947
12585
  case OpKind.Variable:
@@ -11950,6 +12588,19 @@ function reifyCreateOperations(view, ops) {
11950
12588
  }
11951
12589
  OpList.replace(op, createStatementOp(new DeclareVarStmt(op.variable.name, op.initializer, undefined, StmtModifier.Final)));
11952
12590
  break;
12591
+ case OpKind.Namespace:
12592
+ switch (op.active) {
12593
+ case Namespace.HTML:
12594
+ OpList.replace(op, namespaceHTML());
12595
+ break;
12596
+ case Namespace.SVG:
12597
+ OpList.replace(op, namespaceSVG());
12598
+ break;
12599
+ case Namespace.Math:
12600
+ OpList.replace(op, namespaceMath());
12601
+ break;
12602
+ }
12603
+ break;
11953
12604
  case OpKind.Statement:
11954
12605
  // Pass statement operations directly through.
11955
12606
  break;
@@ -11958,48 +12609,66 @@ function reifyCreateOperations(view, ops) {
11958
12609
  }
11959
12610
  }
11960
12611
  }
11961
- function reifyUpdateOperations(_view, ops) {
12612
+ function reifyUpdateOperations(_unit, ops) {
11962
12613
  for (const op of ops) {
11963
12614
  transformExpressionsInOp(op, reifyIrExpression, VisitorContextFlag.None);
11964
12615
  switch (op.kind) {
11965
12616
  case OpKind.Advance:
11966
- OpList.replace(op, advance(op.delta));
12617
+ OpList.replace(op, advance(op.delta, op.sourceSpan));
11967
12618
  break;
11968
12619
  case OpKind.Property:
11969
- OpList.replace(op, property(op.name, op.expression));
12620
+ if (op.expression instanceof Interpolation) {
12621
+ OpList.replace(op, propertyInterpolate(op.name, op.expression.strings, op.expression.expressions, op.sanitizer, op.sourceSpan));
12622
+ }
12623
+ else {
12624
+ OpList.replace(op, property(op.name, op.expression, op.sanitizer, op.sourceSpan));
12625
+ }
11970
12626
  break;
11971
12627
  case OpKind.StyleProp:
11972
- OpList.replace(op, styleProp(op.name, op.expression, op.unit));
12628
+ if (op.expression instanceof Interpolation) {
12629
+ OpList.replace(op, stylePropInterpolate(op.name, op.expression.strings, op.expression.expressions, op.unit));
12630
+ }
12631
+ else {
12632
+ OpList.replace(op, styleProp(op.name, op.expression, op.unit));
12633
+ }
11973
12634
  break;
11974
12635
  case OpKind.ClassProp:
11975
12636
  OpList.replace(op, classProp(op.name, op.expression));
11976
12637
  break;
11977
12638
  case OpKind.StyleMap:
11978
- OpList.replace(op, styleMap(op.expression));
12639
+ if (op.expression instanceof Interpolation) {
12640
+ OpList.replace(op, styleMapInterpolate(op.expression.strings, op.expression.expressions));
12641
+ }
12642
+ else {
12643
+ OpList.replace(op, styleMap(op.expression));
12644
+ }
11979
12645
  break;
11980
12646
  case OpKind.ClassMap:
11981
- OpList.replace(op, classMap(op.expression));
11982
- break;
11983
- case OpKind.InterpolateProperty:
11984
- OpList.replace(op, propertyInterpolate(op.name, op.strings, op.expressions));
11985
- break;
11986
- case OpKind.InterpolateStyleProp:
11987
- OpList.replace(op, stylePropInterpolate(op.name, op.strings, op.expressions, op.unit));
11988
- break;
11989
- case OpKind.InterpolateStyleMap:
11990
- OpList.replace(op, styleMapInterpolate(op.strings, op.expressions));
11991
- break;
11992
- case OpKind.InterpolateClassMap:
11993
- OpList.replace(op, classMapInterpolate(op.strings, op.expressions));
12647
+ if (op.expression instanceof Interpolation) {
12648
+ OpList.replace(op, classMapInterpolate(op.expression.strings, op.expression.expressions));
12649
+ }
12650
+ else {
12651
+ OpList.replace(op, classMap(op.expression));
12652
+ }
11994
12653
  break;
11995
12654
  case OpKind.InterpolateText:
11996
- OpList.replace(op, textInterpolate(op.strings, op.expressions));
12655
+ OpList.replace(op, textInterpolate(op.interpolation.strings, op.interpolation.expressions, op.sourceSpan));
11997
12656
  break;
11998
12657
  case OpKind.Attribute:
11999
- OpList.replace(op, attribute(op.name, op.value));
12658
+ if (op.expression instanceof Interpolation) {
12659
+ OpList.replace(op, attributeInterpolate(op.name, op.expression.strings, op.expression.expressions, op.sanitizer));
12660
+ }
12661
+ else {
12662
+ OpList.replace(op, attribute(op.name, op.expression, op.sanitizer));
12663
+ }
12000
12664
  break;
12001
- case OpKind.InterpolateAttribute:
12002
- OpList.replace(op, attributeInterpolate(op.name, op.strings, op.expressions));
12665
+ case OpKind.HostProperty:
12666
+ if (op.expression instanceof Interpolation) {
12667
+ throw new Error('not yet handled');
12668
+ }
12669
+ else {
12670
+ OpList.replace(op, hostProperty(op.name, op.expression));
12671
+ }
12003
12672
  break;
12004
12673
  case OpKind.Variable:
12005
12674
  if (op.variable.name === null) {
@@ -12061,6 +12730,8 @@ function reifyIrExpression(expr) {
12061
12730
  return pipeBind(expr.slot, expr.varOffset, expr.args);
12062
12731
  case ExpressionKind.PipeBindingVariadic:
12063
12732
  return pipeBindV(expr.slot, expr.varOffset, expr.args);
12733
+ case ExpressionKind.SanitizerExpr:
12734
+ return importExpr(sanitizerIdentifierMap.get(expr.fn));
12064
12735
  default:
12065
12736
  throw new Error(`AssertionError: Unsupported reification of ir.Expression kind: ${ExpressionKind[expr.kind]}`);
12066
12737
  }
@@ -12069,10 +12740,9 @@ function reifyIrExpression(expr) {
12069
12740
  * Listeners get turned into a function expression, which may or may not have the `$event`
12070
12741
  * parameter defined.
12071
12742
  */
12072
- function reifyListenerHandler(view, name, handlerOps) {
12073
- const lookForEvent = new LookForEventVisitor();
12743
+ function reifyListenerHandler(unit, name, handlerOps, consumesDollarEvent) {
12074
12744
  // First, reify all instruction calls within `handlerOps`.
12075
- reifyUpdateOperations(view, handlerOps);
12745
+ reifyUpdateOperations(unit, handlerOps);
12076
12746
  // Next, extract all the `o.Statement`s from the reified operations. We can expect that at this
12077
12747
  // point, all operations have been converted to statements.
12078
12748
  const handlerStmts = [];
@@ -12082,27 +12752,31 @@ function reifyListenerHandler(view, name, handlerOps) {
12082
12752
  }
12083
12753
  handlerStmts.push(op.statement);
12084
12754
  }
12085
- // Scan the statement list for usages of `$event`. If referenced, we need to generate it as a
12086
- // parameter.
12087
- lookForEvent.visitAllStatements(handlerStmts, null);
12755
+ // If `$event` is referenced, we need to generate it as a parameter.
12088
12756
  const params = [];
12089
- if (lookForEvent.seenEventRead) {
12757
+ if (consumesDollarEvent) {
12090
12758
  // We need the `$event` parameter.
12091
12759
  params.push(new FnParam('$event'));
12092
12760
  }
12093
12761
  return fn(params, handlerStmts, undefined, undefined, name);
12094
12762
  }
12095
- /**
12096
- * Visitor which scans for reads of the `$event` special variable.
12097
- */
12098
- class LookForEventVisitor extends RecursiveAstVisitor$1 {
12099
- constructor() {
12100
- super(...arguments);
12101
- this.seenEventRead = false;
12102
- }
12103
- visitReadVarExpr(ast, context) {
12104
- if (ast.name === '$event') {
12105
- this.seenEventRead = true;
12763
+
12764
+ function phaseRemoveEmptyBindings(job) {
12765
+ for (const unit of job.units) {
12766
+ for (const op of unit.update) {
12767
+ switch (op.kind) {
12768
+ case OpKind.Attribute:
12769
+ case OpKind.Binding:
12770
+ case OpKind.ClassProp:
12771
+ case OpKind.ClassMap:
12772
+ case OpKind.Property:
12773
+ case OpKind.StyleProp:
12774
+ case OpKind.StyleMap:
12775
+ if (op.expression instanceof EmptyExpr) {
12776
+ OpList.remove(op);
12777
+ }
12778
+ break;
12779
+ }
12106
12780
  }
12107
12781
  }
12108
12782
  }
@@ -12113,9 +12787,9 @@ class LookForEventVisitor extends RecursiveAstVisitor$1 {
12113
12787
  * that store those contexts (for contexts accessed via the `nextContext()` instruction).
12114
12788
  */
12115
12789
  function phaseResolveContexts(cpl) {
12116
- for (const view of cpl.views.values()) {
12117
- processLexicalScope$1(view, view.create);
12118
- processLexicalScope$1(view, view.update);
12790
+ for (const unit of cpl.units) {
12791
+ processLexicalScope$1(unit, unit.create);
12792
+ processLexicalScope$1(unit, unit.update);
12119
12793
  }
12120
12794
  }
12121
12795
  function processLexicalScope$1(view, ops) {
@@ -12153,6 +12827,30 @@ function processLexicalScope$1(view, ops) {
12153
12827
  }
12154
12828
  }
12155
12829
 
12830
+ /**
12831
+ * Any variable inside a listener with the name `$event` will be transformed into a output lexical
12832
+ * read immediately, and does not participate in any of the normal logic for handling variables.
12833
+ */
12834
+ function phaseResolveDollarEvent(cpl) {
12835
+ for (const [_, view] of cpl.views) {
12836
+ resolveDollarEvent(view, view.create);
12837
+ resolveDollarEvent(view, view.update);
12838
+ }
12839
+ }
12840
+ function resolveDollarEvent(view, ops) {
12841
+ for (const op of ops) {
12842
+ if (op.kind === OpKind.Listener) {
12843
+ transformExpressionsInOp(op, (expr) => {
12844
+ if (expr instanceof LexicalReadExpr && expr.name === '$event') {
12845
+ op.consumesDollarEvent = true;
12846
+ return new ReadVarExpr(expr.name);
12847
+ }
12848
+ return expr;
12849
+ }, VisitorContextFlag.InChildOperation);
12850
+ }
12851
+ }
12852
+ }
12853
+
12156
12854
  /**
12157
12855
  * Resolves lexical references in views (`ir.LexicalReadExpr`) to either a target variable or to
12158
12856
  * property reads on the top-level component context.
@@ -12161,12 +12859,12 @@ function processLexicalScope$1(view, ops) {
12161
12859
  * views.
12162
12860
  */
12163
12861
  function phaseResolveNames(cpl) {
12164
- for (const [_, view] of cpl.views) {
12165
- processLexicalScope(view, view.create, null);
12166
- processLexicalScope(view, view.update, null);
12862
+ for (const unit of cpl.units) {
12863
+ processLexicalScope(unit, unit.create, null);
12864
+ processLexicalScope(unit, unit.update, null);
12167
12865
  }
12168
12866
  }
12169
- function processLexicalScope(view, ops, savedView) {
12867
+ function processLexicalScope(unit, ops, savedView) {
12170
12868
  // Maps names defined in the lexical scope of this template to the `ir.XrefId`s of the variable
12171
12869
  // declarations which represent those values.
12172
12870
  //
@@ -12200,7 +12898,7 @@ function processLexicalScope(view, ops, savedView) {
12200
12898
  case OpKind.Listener:
12201
12899
  // Listener functions have separate variable declarations, so process them as a separate
12202
12900
  // lexical scope.
12203
- processLexicalScope(view, op.handlerOps, savedView);
12901
+ processLexicalScope(unit, op.handlerOps, savedView);
12204
12902
  break;
12205
12903
  }
12206
12904
  }
@@ -12208,7 +12906,11 @@ function processLexicalScope(view, ops, savedView) {
12208
12906
  // scope. Also, look for `ir.RestoreViewExpr`s and match them with the snapshotted view context
12209
12907
  // variable.
12210
12908
  for (const op of ops) {
12211
- transformExpressionsInOp(op, expr => {
12909
+ if (op.kind == OpKind.Listener) {
12910
+ // Listeners were already processed above with their own scopes.
12911
+ continue;
12912
+ }
12913
+ transformExpressionsInOp(op, (expr, flags) => {
12212
12914
  if (expr instanceof LexicalReadExpr) {
12213
12915
  // `expr` is a read of a name within the lexical scope of this view.
12214
12916
  // Either that name is defined within the current view, or it represents a property from the
@@ -12219,7 +12921,7 @@ function processLexicalScope(view, ops, savedView) {
12219
12921
  }
12220
12922
  else {
12221
12923
  // Reading from the component context.
12222
- return new ReadPropExpr(new ContextExpr(view.tpl.root.xref), expr.name);
12924
+ return new ReadPropExpr(new ContextExpr(unit.job.root.xref), expr.name);
12223
12925
  }
12224
12926
  }
12225
12927
  else if (expr instanceof RestoreViewExpr && typeof expr.view === 'number') {
@@ -12227,7 +12929,7 @@ function processLexicalScope(view, ops, savedView) {
12227
12929
  // parent creation list. We expect to find that we captured the `savedView` previously, and
12228
12930
  // that it matches the expected view to be restored.
12229
12931
  if (savedView === null || savedView.view !== expr.view) {
12230
- throw new Error(`AssertionError: no saved view ${expr.view} from view ${view.xref}`);
12932
+ throw new Error(`AssertionError: no saved view ${expr.view} from view ${unit.xref}`);
12231
12933
  }
12232
12934
  expr.view = new ReadVariableExpr(savedView.variable);
12233
12935
  return expr;
@@ -12242,14 +12944,61 @@ function processLexicalScope(view, ops, savedView) {
12242
12944
  if (expr instanceof LexicalReadExpr) {
12243
12945
  throw new Error(`AssertionError: no lexical reads should remain, but found read of ${expr.name}`);
12244
12946
  }
12245
- });
12947
+ });
12948
+ }
12949
+ }
12950
+
12951
+ /**
12952
+ * Mapping of security contexts to sanitizer function for that context.
12953
+ */
12954
+ const sanitizers = new Map([
12955
+ [SecurityContext.HTML, SanitizerFn.Html], [SecurityContext.SCRIPT, SanitizerFn.Script],
12956
+ [SecurityContext.STYLE, SanitizerFn.Style], [SecurityContext.URL, SanitizerFn.Url],
12957
+ [SecurityContext.RESOURCE_URL, SanitizerFn.ResourceUrl]
12958
+ ]);
12959
+ /**
12960
+ * Resolves sanitization functions for ops that need them.
12961
+ */
12962
+ function phaseResolveSanitizers(cpl) {
12963
+ for (const [_, view] of cpl.views) {
12964
+ const elements = getElementsByXrefId(view);
12965
+ let sanitizerFn;
12966
+ for (const op of view.update) {
12967
+ switch (op.kind) {
12968
+ case OpKind.Property:
12969
+ case OpKind.Attribute:
12970
+ sanitizerFn = sanitizers.get(op.securityContext) || null;
12971
+ op.sanitizer = sanitizerFn ? new SanitizerExpr(sanitizerFn) : null;
12972
+ // If there was no sanitization function found based on the security context of an
12973
+ // attribute/property, check whether this attribute/property is one of the
12974
+ // security-sensitive <iframe> attributes (and that the current element is actually an
12975
+ // <iframe>).
12976
+ if (op.sanitizer === null) {
12977
+ const ownerOp = elements.get(op.target);
12978
+ if (ownerOp === undefined) {
12979
+ throw Error('Property should have an element-like owner');
12980
+ }
12981
+ if (isIframeElement$1(ownerOp) && isIframeSecuritySensitiveAttr(op.name)) {
12982
+ op.sanitizer = new SanitizerExpr(SanitizerFn.IframeAttribute);
12983
+ }
12984
+ }
12985
+ break;
12986
+ }
12987
+ }
12246
12988
  }
12247
12989
  }
12990
+ /**
12991
+ * Checks whether the given op represents an iframe element.
12992
+ */
12993
+ function isIframeElement$1(op) {
12994
+ return (op.kind === OpKind.Element || op.kind === OpKind.ElementStart) &&
12995
+ op.tag.toLowerCase() === 'iframe';
12996
+ }
12248
12997
 
12249
12998
  function phaseSaveRestoreView(cpl) {
12250
12999
  for (const view of cpl.views.values()) {
12251
13000
  view.create.prepend([
12252
- createVariableOp(view.tpl.allocateXrefId(), {
13001
+ createVariableOp(view.job.allocateXrefId(), {
12253
13002
  kind: SemanticVariableKind.SavedView,
12254
13003
  name: null,
12255
13004
  view: view.xref,
@@ -12279,7 +13028,7 @@ function phaseSaveRestoreView(cpl) {
12279
13028
  }
12280
13029
  function addSaveRestoreViewOperationToListener(view, op) {
12281
13030
  op.handlerOps.prepend([
12282
- createVariableOp(view.tpl.allocateXrefId(), {
13031
+ createVariableOp(view.job.allocateXrefId(), {
12283
13032
  kind: SemanticVariableKind.Context,
12284
13033
  name: null,
12285
13034
  view: view.xref,
@@ -12373,6 +13122,40 @@ function phaseSlotAllocation(cpl) {
12373
13122
  }
12374
13123
  }
12375
13124
 
13125
+ /**
13126
+ * Transforms special-case bindings with 'style' or 'class' in their names. Must run before the
13127
+ * main binding specialization pass.
13128
+ */
13129
+ function phaseStyleBindingSpecialization(cpl) {
13130
+ for (const unit of cpl.units) {
13131
+ for (const op of unit.update) {
13132
+ if (op.kind !== OpKind.Binding) {
13133
+ continue;
13134
+ }
13135
+ switch (op.bindingKind) {
13136
+ case BindingKind.ClassName:
13137
+ if (op.expression instanceof Interpolation) {
13138
+ throw new Error(`Unexpected interpolation in ClassName binding`);
13139
+ }
13140
+ OpList.replace(op, createClassPropOp(op.target, op.name, op.expression, op.sourceSpan));
13141
+ break;
13142
+ case BindingKind.StyleProperty:
13143
+ OpList.replace(op, createStylePropOp(op.target, op.name, op.expression, op.unit, op.sourceSpan));
13144
+ break;
13145
+ case BindingKind.Property:
13146
+ case BindingKind.Template:
13147
+ if (op.name === 'style') {
13148
+ OpList.replace(op, createStyleMapOp(op.target, op.expression, op.sourceSpan));
13149
+ }
13150
+ else if (op.name === 'class') {
13151
+ OpList.replace(op, createClassMapOp(op.target, op.expression, op.sourceSpan));
13152
+ }
13153
+ break;
13154
+ }
13155
+ }
13156
+ }
13157
+ }
13158
+
12376
13159
  /**
12377
13160
  * Find all assignments and usages of temporary variables, which are linked to each other with cross
12378
13161
  * references. Generate names for each cross-reference, and add a `DeclareVarStmt` to initialize
@@ -12383,38 +13166,58 @@ function phaseSlotAllocation(cpl) {
12383
13166
  * Implement an algorithm for reuse.
12384
13167
  */
12385
13168
  function phaseTemporaryVariables(cpl) {
12386
- for (const view of cpl.views.values()) {
13169
+ for (const unit of cpl.units) {
12387
13170
  let opCount = 0;
12388
13171
  let generatedStatements = [];
12389
- for (const op of view.ops()) {
12390
- let count = 0;
12391
- let xrefs = new Set();
12392
- let defs = new Map();
13172
+ for (const op of unit.ops()) {
13173
+ // Identify the final time each temp var is read.
13174
+ const finalReads = new Map();
12393
13175
  visitExpressionsInOp(op, expr => {
12394
- if (expr instanceof ReadTemporaryExpr || expr instanceof AssignTemporaryExpr) {
12395
- xrefs.add(expr.xref);
13176
+ if (expr instanceof ReadTemporaryExpr) {
13177
+ finalReads.set(expr.xref, expr);
12396
13178
  }
12397
13179
  });
12398
- for (const xref of xrefs) {
12399
- // TODO: Exactly replicate the naming scheme used by `TemplateDefinitionBuilder`. It seems
12400
- // to rely on an expression index instead of an op index.
12401
- defs.set(xref, `tmp_${opCount}_${count++}`);
12402
- }
13180
+ // Name the temp vars, accounting for the fact that a name can be reused after it has been
13181
+ // read for the final time.
13182
+ let count = 0;
13183
+ const assigned = new Set();
13184
+ const released = new Set();
13185
+ const defs = new Map();
12403
13186
  visitExpressionsInOp(op, expr => {
12404
- if (expr instanceof ReadTemporaryExpr || expr instanceof AssignTemporaryExpr) {
12405
- const name = defs.get(expr.xref);
12406
- if (name === undefined) {
12407
- throw new Error('Found xref with unassigned name');
13187
+ if (expr instanceof AssignTemporaryExpr) {
13188
+ if (!assigned.has(expr.xref)) {
13189
+ assigned.add(expr.xref);
13190
+ // TODO: Exactly replicate the naming scheme used by `TemplateDefinitionBuilder`.
13191
+ // It seems to rely on an expression index instead of an op index.
13192
+ defs.set(expr.xref, `tmp_${opCount}_${count++}`);
13193
+ }
13194
+ assignName(defs, expr);
13195
+ }
13196
+ else if (expr instanceof ReadTemporaryExpr) {
13197
+ if (finalReads.get(expr.xref) === expr) {
13198
+ released.add(expr.xref);
13199
+ count--;
12408
13200
  }
12409
- expr.name = name;
13201
+ assignName(defs, expr);
12410
13202
  }
12411
13203
  });
12412
- generatedStatements.push(...Array.from(defs.values())
13204
+ // Add declarations for the temp vars.
13205
+ generatedStatements.push(...Array.from(new Set(defs.values()))
12413
13206
  .map(name => createStatementOp(new DeclareVarStmt(name))));
12414
13207
  opCount++;
12415
13208
  }
12416
- view.update.prepend(generatedStatements);
13209
+ unit.update.prepend(generatedStatements);
13210
+ }
13211
+ }
13212
+ /**
13213
+ * Assigns a name to the temporary variable in the given temporary variable expression.
13214
+ */
13215
+ function assignName(names, expr) {
13216
+ const name = names.get(expr.xref);
13217
+ if (name === undefined) {
13218
+ throw new Error(`Found xref with unassigned name: ${expr.xref}`);
12417
13219
  }
13220
+ expr.name = name;
12418
13221
  }
12419
13222
 
12420
13223
  /**
@@ -12435,13 +13238,13 @@ function phaseTemporaryVariables(cpl) {
12435
13238
  * To guarantee correctness, analysis of "fences" in the instruction lists is used to determine
12436
13239
  * which optimizations are safe to perform.
12437
13240
  */
12438
- function phaseVariableOptimization(cpl, options) {
12439
- for (const [_, view] of cpl.views) {
12440
- optimizeVariablesInOpList(view.create, options);
12441
- optimizeVariablesInOpList(view.update, options);
12442
- for (const op of view.create) {
13241
+ function phaseVariableOptimization(job) {
13242
+ for (const unit of job.units) {
13243
+ optimizeVariablesInOpList(unit.create, job.compatibility);
13244
+ optimizeVariablesInOpList(unit.update, job.compatibility);
13245
+ for (const op of unit.create) {
12443
13246
  if (op.kind === OpKind.Listener) {
12444
- optimizeVariablesInOpList(op.handlerOps, options);
13247
+ optimizeVariablesInOpList(op.handlerOps, job.compatibility);
12445
13248
  }
12446
13249
  }
12447
13250
  }
@@ -12482,7 +13285,7 @@ var Fence;
12482
13285
  /**
12483
13286
  * Process a list of operations and optimize variables within that list.
12484
13287
  */
12485
- function optimizeVariablesInOpList(ops, options) {
13288
+ function optimizeVariablesInOpList(ops, compatibility) {
12486
13289
  const varDecls = new Map();
12487
13290
  const varUsages = new Map();
12488
13291
  // Track variables that are used outside of the immediate operation list. For example, within
@@ -12573,7 +13376,8 @@ function optimizeVariablesInOpList(ops, options) {
12573
13376
  const opInfo = opMap.get(targetOp);
12574
13377
  // Is the variable used in this operation?
12575
13378
  if (opInfo.variablesUsed.has(candidate)) {
12576
- if (options.conservative && !allowConservativeInlining(decl, targetOp)) {
13379
+ if (compatibility === CompatibilityMode.TemplateDefinitionBuilder &&
13380
+ !allowConservativeInlining(decl, targetOp)) {
12577
13381
  // We're in conservative mode, and this variable is not eligible for inlining into the
12578
13382
  // target operation in this mode.
12579
13383
  break;
@@ -12782,35 +13586,68 @@ function allowConservativeInlining(decl, target) {
12782
13586
 
12783
13587
  /**
12784
13588
  * Run all transformation phases in the correct order against a `ComponentCompilation`. After this
12785
- * processing, the compilation should be in a state where it can be emitted via `emitTemplateFn`.s
12786
- */
12787
- function transformTemplate(cpl) {
12788
- phaseAttributeExtraction(cpl, /* compatibility */ true);
12789
- phasePipeCreation(cpl);
12790
- phasePipeVariadic(cpl);
12791
- phasePureLiteralStructures(cpl);
12792
- phaseGenerateVariables(cpl);
12793
- phaseSaveRestoreView(cpl);
12794
- phaseResolveNames(cpl);
12795
- phaseResolveContexts(cpl);
12796
- phaseLocalRefs(cpl);
12797
- phaseConstCollection(cpl);
12798
- phaseNullishCoalescing(cpl);
12799
- phaseExpandSafeReads(cpl, true);
12800
- phaseTemporaryVariables(cpl);
12801
- phaseSlotAllocation(cpl);
12802
- phaseVarCounting(cpl);
12803
- phaseGenerateAdvance(cpl);
12804
- phaseNaming(cpl, /* compatibility */ true);
12805
- phaseVariableOptimization(cpl, { conservative: true });
12806
- phaseMergeNextContext(cpl);
12807
- phaseNgContainer(cpl);
12808
- phaseEmptyElements(cpl);
12809
- phasePureFunctionExtraction(cpl);
12810
- phaseAlignPipeVariadicVarOffset(cpl);
12811
- phasePropertyOrdering(cpl);
12812
- phaseReify(cpl);
12813
- phaseChaining(cpl);
13589
+ * processing, the compilation should be in a state where it can be emitted.
13590
+ */
13591
+ function transformTemplate(job) {
13592
+ phaseNamespace(job);
13593
+ phaseStyleBindingSpecialization(job);
13594
+ phaseBindingSpecialization(job);
13595
+ phaseAttributeExtraction(job);
13596
+ phaseRemoveEmptyBindings(job);
13597
+ phaseNoListenersOnTemplates(job);
13598
+ phasePipeCreation(job);
13599
+ phasePipeVariadic(job);
13600
+ phasePureLiteralStructures(job);
13601
+ phaseGenerateVariables(job);
13602
+ phaseSaveRestoreView(job);
13603
+ phaseFindAnyCasts(job);
13604
+ phaseResolveDollarEvent(job);
13605
+ phaseResolveNames(job);
13606
+ phaseResolveContexts(job);
13607
+ phaseResolveSanitizers(job);
13608
+ phaseLocalRefs(job);
13609
+ phaseConstCollection(job);
13610
+ phaseNullishCoalescing(job);
13611
+ phaseExpandSafeReads(job);
13612
+ phaseTemporaryVariables(job);
13613
+ phaseSlotAllocation(job);
13614
+ phaseVarCounting(job);
13615
+ phaseGenerateAdvance(job);
13616
+ phaseVariableOptimization(job);
13617
+ phaseNaming(job);
13618
+ phaseMergeNextContext(job);
13619
+ phaseNgContainer(job);
13620
+ phaseEmptyElements(job);
13621
+ phaseNonbindable(job);
13622
+ phasePureFunctionExtraction(job);
13623
+ phaseAlignPipeVariadicVarOffset(job);
13624
+ phasePropertyOrdering(job);
13625
+ phaseReify(job);
13626
+ phaseChaining(job);
13627
+ }
13628
+ /**
13629
+ * Run all transformation phases in the correct order against a `HostBindingCompilationJob`. After
13630
+ * this processing, the compilation should be in a state where it can be emitted.
13631
+ */
13632
+ function transformHostBinding(job) {
13633
+ phaseHostStylePropertyParsing(job);
13634
+ phaseStyleBindingSpecialization(job);
13635
+ phaseBindingSpecialization(job);
13636
+ phasePureLiteralStructures(job);
13637
+ phaseNullishCoalescing(job);
13638
+ phaseExpandSafeReads(job);
13639
+ phaseTemporaryVariables(job);
13640
+ phaseVarCounting(job);
13641
+ phaseVariableOptimization(job);
13642
+ phaseResolveNames(job);
13643
+ phaseResolveContexts(job);
13644
+ // TODO: Figure out how to make this work for host bindings.
13645
+ // phaseResolveSanitizers(job);
13646
+ phaseNaming(job);
13647
+ phasePureFunctionExtraction(job);
13648
+ phasePropertyOrdering(job);
13649
+ phaseReify(job);
13650
+ phaseChaining(job);
12814
13651
  }
12815
13652
  /**
12816
13653
  * Compile all views in the given `ComponentCompilation` into the final template function, which may
@@ -12822,7 +13659,7 @@ function emitTemplateFn(tpl, pool) {
12822
13659
  return rootFn;
12823
13660
  }
12824
13661
  function emitChildViews(parent, pool) {
12825
- for (const view of parent.tpl.views.values()) {
13662
+ for (const view of parent.job.views.values()) {
12826
13663
  if (view.parent !== parent.xref) {
12827
13664
  continue;
12828
13665
  }
@@ -12873,151 +13710,85 @@ function maybeGenerateRfBlock(flag, statements) {
12873
13710
  ifStmt(new BinaryOperatorExpr(BinaryOperator.BitwiseAnd, variable('rf'), literal(flag)), statements),
12874
13711
  ];
12875
13712
  }
12876
-
12877
- /**
12878
- * Compilation-in-progress of a whole component's template, including the main template and any
12879
- * embedded views or host bindings.
12880
- */
12881
- class ComponentCompilation {
12882
- constructor(componentName, pool) {
12883
- this.componentName = componentName;
12884
- this.pool = pool;
12885
- /**
12886
- * Tracks the next `ir.XrefId` which can be assigned as template structures are ingested.
12887
- */
12888
- this.nextXrefId = 0;
12889
- /**
12890
- * Map of view IDs to `ViewCompilation`s.
12891
- */
12892
- this.views = new Map();
12893
- /**
12894
- * Constant expressions used by operations within this component's compilation.
12895
- *
12896
- * This will eventually become the `consts` array in the component definition.
12897
- */
12898
- this.consts = [];
12899
- // Allocate the root view.
12900
- const root = new ViewCompilation(this, this.allocateXrefId(), null);
12901
- this.views.set(root.xref, root);
12902
- this.root = root;
12903
- }
12904
- /**
12905
- * Add a `ViewCompilation` for a new embedded view to this compilation.
12906
- */
12907
- allocateView(parent) {
12908
- const view = new ViewCompilation(this, this.allocateXrefId(), parent);
12909
- this.views.set(view.xref, view);
12910
- return view;
12911
- }
12912
- /**
12913
- * Generate a new unique `ir.XrefId`.
12914
- */
12915
- allocateXrefId() {
12916
- return this.nextXrefId++;
13713
+ function emitHostBindingFunction(job) {
13714
+ if (job.fnName === null) {
13715
+ throw new Error(`AssertionError: host binding function is unnamed`);
12917
13716
  }
12918
- /**
12919
- * Add a constant `o.Expression` to the compilation and return its index in the `consts` array.
12920
- */
12921
- addConst(newConst) {
12922
- for (let idx = 0; idx < this.consts.length; idx++) {
12923
- if (this.consts[idx].isEquivalent(newConst)) {
12924
- return idx;
12925
- }
13717
+ const createStatements = [];
13718
+ for (const op of job.create) {
13719
+ if (op.kind !== OpKind.Statement) {
13720
+ throw new Error(`AssertionError: expected all create ops to have been compiled, but got ${OpKind[op.kind]}`);
12926
13721
  }
12927
- const idx = this.consts.length;
12928
- this.consts.push(newConst);
12929
- return idx;
12930
- }
12931
- }
12932
- /**
12933
- * Compilation-in-progress of an individual view within a template.
12934
- */
12935
- class ViewCompilation {
12936
- constructor(tpl, xref, parent) {
12937
- this.tpl = tpl;
12938
- this.xref = xref;
12939
- this.parent = parent;
12940
- /**
12941
- * Name of the function which will be generated for this view.
12942
- *
12943
- * May be `null` if not yet determined.
12944
- */
12945
- this.fnName = null;
12946
- /**
12947
- * List of creation operations for this view.
12948
- *
12949
- * Creation operations may internally contain other operations, including update operations.
12950
- */
12951
- this.create = new OpList();
12952
- /**
12953
- * List of update operations for this view.
12954
- */
12955
- this.update = new OpList();
12956
- /**
12957
- * Map of declared variables available within this view to the property on the context object
12958
- * which they alias.
12959
- */
12960
- this.contextVariables = new Map();
12961
- /**
12962
- * Number of declaration slots used within this view, or `null` if slots have not yet been
12963
- * allocated.
12964
- */
12965
- this.decls = null;
12966
- /**
12967
- * Number of variable slots used within this view, or `null` if variables have not yet been
12968
- * counted.
12969
- */
12970
- this.vars = null;
13722
+ createStatements.push(op.statement);
12971
13723
  }
12972
- /**
12973
- * Iterate over all `ir.Op`s within this view.
12974
- *
12975
- * Some operations may have child operations, which this iterator will visit.
12976
- */
12977
- *ops() {
12978
- for (const op of this.create) {
12979
- yield op;
12980
- if (op.kind === OpKind.Listener) {
12981
- for (const listenerOp of op.handlerOps) {
12982
- yield listenerOp;
12983
- }
12984
- }
12985
- }
12986
- for (const op of this.update) {
12987
- yield op;
13724
+ const updateStatements = [];
13725
+ for (const op of job.update) {
13726
+ if (op.kind !== OpKind.Statement) {
13727
+ throw new Error(`AssertionError: expected all update ops to have been compiled, but got ${OpKind[op.kind]}`);
12988
13728
  }
13729
+ updateStatements.push(op.statement);
13730
+ }
13731
+ if (createStatements.length === 0 && updateStatements.length === 0) {
13732
+ return null;
12989
13733
  }
13734
+ const createCond = maybeGenerateRfBlock(1, createStatements);
13735
+ const updateCond = maybeGenerateRfBlock(2, updateStatements);
13736
+ return fn([
13737
+ new FnParam('rf'),
13738
+ new FnParam('ctx'),
13739
+ ], [
13740
+ ...createCond,
13741
+ ...updateCond,
13742
+ ],
13743
+ /* type */ undefined, /* sourceSpan */ undefined, job.fnName);
12990
13744
  }
12991
13745
 
12992
- const BINARY_OPERATORS = new Map([
12993
- ['&&', BinaryOperator.And],
12994
- ['>', BinaryOperator.Bigger],
12995
- ['>=', BinaryOperator.BiggerEquals],
12996
- ['&', BinaryOperator.BitwiseAnd],
12997
- ['/', BinaryOperator.Divide],
12998
- ['==', BinaryOperator.Equals],
12999
- ['===', BinaryOperator.Identical],
13000
- ['<', BinaryOperator.Lower],
13001
- ['<=', BinaryOperator.LowerEquals],
13002
- ['-', BinaryOperator.Minus],
13003
- ['%', BinaryOperator.Modulo],
13004
- ['*', BinaryOperator.Multiply],
13005
- ['!=', BinaryOperator.NotEquals],
13006
- ['!==', BinaryOperator.NotIdentical],
13007
- ['??', BinaryOperator.NullishCoalesce],
13008
- ['||', BinaryOperator.Or],
13009
- ['+', BinaryOperator.Plus],
13010
- ]);
13011
-
13746
+ const compatibilityMode = CompatibilityMode.TemplateDefinitionBuilder;
13012
13747
  /**
13013
13748
  * Process a template AST and convert it into a `ComponentCompilation` in the intermediate
13014
13749
  * representation.
13015
13750
  */
13016
- function ingest(componentName, template, constantPool) {
13017
- const cpl = new ComponentCompilation(componentName, constantPool);
13751
+ function ingestComponent(componentName, template, constantPool) {
13752
+ const cpl = new ComponentCompilationJob(componentName, constantPool, compatibilityMode);
13018
13753
  ingestNodes(cpl.root, template);
13019
13754
  return cpl;
13020
13755
  }
13756
+ /**
13757
+ * Process a host binding AST and convert it into a `HostBindingCompilationJob` in the intermediate
13758
+ * representation.
13759
+ */
13760
+ function ingestHostBinding(input, bindingParser, constantPool) {
13761
+ const job = new HostBindingCompilationJob(input.componentName, constantPool, compatibilityMode);
13762
+ for (const property of input.properties ?? []) {
13763
+ ingestHostProperty(job, property);
13764
+ }
13765
+ for (const event of input.events ?? []) {
13766
+ ingestHostEvent(job, event);
13767
+ }
13768
+ return job;
13769
+ }
13770
+ // TODO: We should refactor the parser to use the same types and structures for host bindings as
13771
+ // with ordinary components. This would allow us to share a lot more ingestion code.
13772
+ function ingestHostProperty(job, property) {
13773
+ let expression;
13774
+ const ast = property.expression.ast;
13775
+ if (ast instanceof Interpolation$1) {
13776
+ expression =
13777
+ new Interpolation(ast.strings, ast.expressions.map(expr => convertAst(expr, job)));
13778
+ }
13779
+ else {
13780
+ expression = convertAst(ast, job);
13781
+ }
13782
+ let bindingKind = BindingKind.Property;
13783
+ // TODO: this should really be handled in the parser.
13784
+ if (property.name.startsWith('attr.')) {
13785
+ property.name = property.name.substring('attr.'.length);
13786
+ bindingKind = BindingKind.Attribute;
13787
+ }
13788
+ job.update.push(createBindingOp(job.root.xref, bindingKind, property.name, expression, null, SecurityContext
13789
+ .NONE /* TODO: what should we pass as security context? Passing NONE for now. */, false, property.sourceSpan));
13790
+ }
13791
+ function ingestHostEvent(job, event) { }
13021
13792
  /**
13022
13793
  * Ingest the nodes of a template AST into the given `ViewCompilation`.
13023
13794
  */
@@ -13048,21 +13819,27 @@ function ingestElement(view, element) {
13048
13819
  for (const attr of element.attributes) {
13049
13820
  staticAttributes[attr.name] = attr.value;
13050
13821
  }
13051
- const id = view.tpl.allocateXrefId();
13052
- const startOp = createElementStartOp(element.name, id);
13822
+ const id = view.job.allocateXrefId();
13823
+ const [namespaceKey, elementName] = splitNsName(element.name);
13824
+ const startOp = createElementStartOp(elementName, id, namespaceForKey(namespaceKey), element.startSourceSpan);
13053
13825
  view.create.push(startOp);
13054
13826
  ingestBindings(view, startOp, element);
13055
13827
  ingestReferences(startOp, element);
13056
13828
  ingestNodes(view, element.children);
13057
- view.create.push(createElementEndOp(id));
13829
+ view.create.push(createElementEndOp(id, element.endSourceSpan));
13058
13830
  }
13059
13831
  /**
13060
13832
  * Ingest an `ng-template` node from the AST into the given `ViewCompilation`.
13061
13833
  */
13062
13834
  function ingestTemplate(view, tmpl) {
13063
- const childView = view.tpl.allocateView(view.xref);
13835
+ const childView = view.job.allocateView(view.xref);
13836
+ let tagNameWithoutNamespace = tmpl.tagName;
13837
+ let namespacePrefix = '';
13838
+ if (tmpl.tagName) {
13839
+ [namespacePrefix, tagNameWithoutNamespace] = splitNsName(tmpl.tagName);
13840
+ }
13064
13841
  // TODO: validate the fallback tag name here.
13065
- const tplOp = createTemplateOp(childView.xref, tmpl.tagName ?? 'ng-template');
13842
+ const tplOp = createTemplateOp(childView.xref, tagNameWithoutNamespace ?? 'ng-template', namespaceForKey(namespacePrefix), tmpl.startSourceSpan);
13066
13843
  view.create.push(tplOp);
13067
13844
  ingestBindings(view, tplOp, tmpl);
13068
13845
  ingestReferences(tplOp, tmpl);
@@ -13075,7 +13852,7 @@ function ingestTemplate(view, tmpl) {
13075
13852
  * Ingest a literal text node from the AST into the given `ViewCompilation`.
13076
13853
  */
13077
13854
  function ingestText(view, text) {
13078
- view.create.push(createTextOp(view.tpl.allocateXrefId(), text.value));
13855
+ view.create.push(createTextOp(view.job.allocateXrefId(), text.value, text.sourceSpan));
13079
13856
  }
13080
13857
  /**
13081
13858
  * Ingest an interpolated text node from the AST into the given `ViewCompilation`.
@@ -13085,12 +13862,12 @@ function ingestBoundText(view, text) {
13085
13862
  if (value instanceof ASTWithSource) {
13086
13863
  value = value.ast;
13087
13864
  }
13088
- if (!(value instanceof Interpolation)) {
13865
+ if (!(value instanceof Interpolation$1)) {
13089
13866
  throw new Error(`AssertionError: expected Interpolation for BoundText node, got ${value.constructor.name}`);
13090
13867
  }
13091
- const textXref = view.tpl.allocateXrefId();
13092
- view.create.push(createTextOp(textXref, ''));
13093
- view.update.push(createInterpolateTextOp(textXref, value.strings, value.expressions.map(expr => convertAst(expr, view.tpl))));
13868
+ const textXref = view.job.allocateXrefId();
13869
+ view.create.push(createTextOp(textXref, '', text.sourceSpan));
13870
+ view.update.push(createInterpolateTextOp(textXref, new Interpolation(value.strings, value.expressions.map(expr => convertAst(expr, view.job))), text.sourceSpan));
13094
13871
  }
13095
13872
  /**
13096
13873
  * Convert a template AST expression into an output AST expression.
@@ -13100,7 +13877,7 @@ function convertAst(ast, cpl) {
13100
13877
  return convertAst(ast.ast, cpl);
13101
13878
  }
13102
13879
  else if (ast instanceof PropertyRead) {
13103
- if (ast.receiver instanceof ImplicitReceiver) {
13880
+ if (ast.receiver instanceof ImplicitReceiver && !(ast.receiver instanceof ThisReceiver)) {
13104
13881
  return new LexicalReadExpr(ast.name);
13105
13882
  }
13106
13883
  else {
@@ -13187,24 +13964,33 @@ function ingestBindings(view, op, element) {
13187
13964
  if (element instanceof Template) {
13188
13965
  for (const attr of element.templateAttrs) {
13189
13966
  if (attr instanceof TextAttribute) {
13190
- view.update.push(createAttributeOp(op.xref, ElementAttributeKind.Template, attr.name, literal(attr.value)));
13967
+ ingestBinding(view, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, true);
13191
13968
  }
13192
13969
  else {
13193
- ingestPropertyBinding(view, op.xref, ElementAttributeKind.Template, attr);
13970
+ ingestBinding(view, op.xref, attr.name, attr.value, attr.type, attr.unit, attr.securityContext, attr.sourceSpan, true);
13194
13971
  }
13195
13972
  }
13196
13973
  }
13197
13974
  for (const attr of element.attributes) {
13198
- // This is only attribute TextLiteral bindings, such as `attr.foo="bar'`. This can never be
13975
+ // This is only attribute TextLiteral bindings, such as `attr.foo="bar"`. This can never be
13199
13976
  // `[attr.foo]="bar"` or `attr.foo="{{bar}}"`, both of which will be handled as inputs with
13200
13977
  // `BindingType.Attribute`.
13201
- view.update.push(createAttributeOp(op.xref, ElementAttributeKind.Attribute, attr.name, literal(attr.value)));
13978
+ ingestBinding(view, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, false);
13202
13979
  }
13203
13980
  for (const input of element.inputs) {
13204
- ingestPropertyBinding(view, op.xref, ElementAttributeKind.Binding, input);
13981
+ ingestBinding(view, op.xref, input.name, input.value, input.type, input.unit, input.securityContext, input.sourceSpan, false);
13205
13982
  }
13206
13983
  for (const output of element.outputs) {
13207
- const listenerOp = createListenerOp(op.xref, output.name, op.tag);
13984
+ let listenerOp;
13985
+ if (output.type === 1 /* e.ParsedEventType.Animation */) {
13986
+ if (output.phase === null) {
13987
+ throw Error('Animation listener should have a phase');
13988
+ }
13989
+ listenerOp = createListenerOpForAnimation(op.xref, output.name, output.phase, op.tag);
13990
+ }
13991
+ else {
13992
+ listenerOp = createListenerOp(op.xref, output.name, op.tag);
13993
+ }
13208
13994
  // if output.handler is a chain, then push each statement from the chain separately, and
13209
13995
  // return the last one?
13210
13996
  let inputExprs;
@@ -13221,7 +14007,7 @@ function ingestBindings(view, op, element) {
13221
14007
  if (inputExprs.length === 0) {
13222
14008
  throw new Error('Expected listener to have non-empty expression list.');
13223
14009
  }
13224
- const expressions = inputExprs.map(expr => convertAst(expr, view.tpl));
14010
+ const expressions = inputExprs.map(expr => convertAst(expr, view.job));
13225
14011
  const returnExpr = expressions.pop();
13226
14012
  for (const expr of expressions) {
13227
14013
  const stmtOp = createStatementOp(new ExpressionStatement(expr));
@@ -13231,95 +14017,29 @@ function ingestBindings(view, op, element) {
13231
14017
  view.create.push(listenerOp);
13232
14018
  }
13233
14019
  }
13234
- function ingestPropertyBinding(view, xref, bindingKind, { name, value, type, unit }) {
14020
+ const BINDING_KINDS = new Map([
14021
+ [0 /* e.BindingType.Property */, BindingKind.Property],
14022
+ [1 /* e.BindingType.Attribute */, BindingKind.Attribute],
14023
+ [2 /* e.BindingType.Class */, BindingKind.ClassName],
14024
+ [3 /* e.BindingType.Style */, BindingKind.StyleProperty],
14025
+ [4 /* e.BindingType.Animation */, BindingKind.Animation],
14026
+ ]);
14027
+ function ingestBinding(view, xref, name, value, type, unit, securityContext, sourceSpan, isTemplateBinding) {
13235
14028
  if (value instanceof ASTWithSource) {
13236
14029
  value = value.ast;
13237
14030
  }
13238
- if (value instanceof Interpolation) {
13239
- switch (type) {
13240
- case 0 /* e.BindingType.Property */:
13241
- if (name === 'style') {
13242
- if (bindingKind !== ElementAttributeKind.Binding) {
13243
- throw Error('Unexpected style binding on ng-template');
13244
- }
13245
- view.update.push(createInterpolateStyleMapOp(xref, value.strings, value.expressions.map(expr => convertAst(expr, view.tpl))));
13246
- }
13247
- else if (name === 'class') {
13248
- if (bindingKind !== ElementAttributeKind.Binding) {
13249
- throw Error('Unexpected class binding on ng-template');
13250
- }
13251
- view.update.push(createInterpolateClassMapOp(xref, value.strings, value.expressions.map(expr => convertAst(expr, view.tpl))));
13252
- }
13253
- else {
13254
- view.update.push(createInterpolatePropertyOp(xref, bindingKind, name, value.strings, value.expressions.map(expr => convertAst(expr, view.tpl))));
13255
- }
13256
- break;
13257
- case 3 /* e.BindingType.Style */:
13258
- if (bindingKind !== ElementAttributeKind.Binding) {
13259
- throw Error('Unexpected style binding on ng-template');
13260
- }
13261
- view.update.push(createInterpolateStylePropOp(xref, name, value.strings, value.expressions.map(expr => convertAst(expr, view.tpl)), unit));
13262
- break;
13263
- case 1 /* e.BindingType.Attribute */:
13264
- if (bindingKind !== ElementAttributeKind.Binding) {
13265
- throw new Error('Attribute bindings on templates are not expected to be valid');
13266
- }
13267
- const attributeInterpolate = createInterpolateAttributeOp(xref, bindingKind, name, value.strings, value.expressions.map(expr => convertAst(expr, view.tpl)));
13268
- view.update.push(attributeInterpolate);
13269
- break;
13270
- case 2 /* e.BindingType.Class */:
13271
- throw Error('Unexpected interpolation in class property binding');
13272
- // TODO: implement remaining binding types.
13273
- case 4 /* e.BindingType.Animation */:
13274
- default:
13275
- throw Error(`Interpolated property binding type not handled: ${type}`);
13276
- }
14031
+ let expression;
14032
+ if (value instanceof Interpolation$1) {
14033
+ expression = new Interpolation(value.strings, value.expressions.map(expr => convertAst(expr, view.job)));
14034
+ }
14035
+ else if (value instanceof AST) {
14036
+ expression = convertAst(value, view.job);
13277
14037
  }
13278
14038
  else {
13279
- switch (type) {
13280
- case 0 /* e.BindingType.Property */:
13281
- // Bindings to [style] are mapped to their own special instruction.
13282
- if (name === 'style') {
13283
- if (bindingKind !== ElementAttributeKind.Binding) {
13284
- throw Error('Unexpected style binding on ng-template');
13285
- }
13286
- view.update.push(createStyleMapOp(xref, convertAst(value, view.tpl)));
13287
- }
13288
- else if (name === 'class') {
13289
- if (bindingKind !== ElementAttributeKind.Binding) {
13290
- throw Error('Unexpected class binding on ng-template');
13291
- }
13292
- view.update.push(createClassMapOp(xref, convertAst(value, view.tpl)));
13293
- }
13294
- else {
13295
- view.update.push(createPropertyOp(xref, bindingKind, name, convertAst(value, view.tpl)));
13296
- }
13297
- break;
13298
- case 3 /* e.BindingType.Style */:
13299
- if (bindingKind !== ElementAttributeKind.Binding) {
13300
- throw Error('Unexpected style binding on ng-template');
13301
- }
13302
- view.update.push(createStylePropOp(xref, name, convertAst(value, view.tpl), unit));
13303
- break;
13304
- case 1 /* e.BindingType.Attribute */:
13305
- if (bindingKind !== ElementAttributeKind.Binding) {
13306
- throw new Error('Attribute bindings on templates are not expected to be valid');
13307
- }
13308
- const attrOp = createAttributeOp(xref, bindingKind, name, convertAst(value, view.tpl));
13309
- view.update.push(attrOp);
13310
- break;
13311
- case 2 /* e.BindingType.Class */:
13312
- if (bindingKind !== ElementAttributeKind.Binding) {
13313
- throw Error('Unexpected class binding on ng-template');
13314
- }
13315
- view.update.push(createClassPropOp(xref, name, convertAst(value, view.tpl)));
13316
- break;
13317
- // TODO: implement remaining binding types.
13318
- case 4 /* e.BindingType.Animation */:
13319
- default:
13320
- throw Error(`Property binding type not handled: ${type}`);
13321
- }
14039
+ expression = value;
13322
14040
  }
14041
+ const kind = BINDING_KINDS.get(type);
14042
+ view.update.push(createBindingOp(xref, kind, name, expression, unit, securityContext, isTemplateBinding, sourceSpan));
13323
14043
  }
13324
14044
  /**
13325
14045
  * Process all of the local references on an element-like structure in the template AST and
@@ -13514,7 +14234,7 @@ class StylingBuilder {
13514
14234
  // CSS custom properties are case-sensitive so we shouldn't normalize them.
13515
14235
  // See: https://www.w3.org/TR/css-variables-1/#defining-variables
13516
14236
  if (!isCssCustomProperty(name)) {
13517
- name = hyphenate(name);
14237
+ name = hyphenate$1(name);
13518
14238
  }
13519
14239
  const { property, hasOverrideFlag, suffix: bindingSuffix } = parseProperty(name);
13520
14240
  suffix = typeof suffix === 'string' && suffix.length !== 0 ? suffix : bindingSuffix;
@@ -13644,7 +14364,7 @@ class StylingBuilder {
13644
14364
  // pipes can be picked up in time before the template is built
13645
14365
  const mapValue = stylingInput.value.visit(valueConverter);
13646
14366
  let reference;
13647
- if (mapValue instanceof Interpolation) {
14367
+ if (mapValue instanceof Interpolation$1) {
13648
14368
  totalBindingSlotsRequired += mapValue.expressions.length;
13649
14369
  reference = isClassBased ? getClassMapInterpolationExpression(mapValue) :
13650
14370
  getStyleMapInterpolationExpression(mapValue);
@@ -13679,7 +14399,7 @@ class StylingBuilder {
13679
14399
  // We need to store the intermediate value so that we don't allocate
13680
14400
  // the strings on each CD.
13681
14401
  let totalBindingSlotsRequired = MIN_STYLING_BINDING_SLOTS_REQUIRED;
13682
- if (value instanceof Interpolation) {
14402
+ if (value instanceof Interpolation$1) {
13683
14403
  totalBindingSlotsRequired += value.expressions.length;
13684
14404
  if (getInterpolationExpressionFn) {
13685
14405
  referenceForCall = getInterpolationExpressionFn(value);
@@ -14323,6 +15043,7 @@ class Parser$1 {
14323
15043
  ast.visit(checker);
14324
15044
  return checker.errors;
14325
15045
  }
15046
+ // Host bindings parsed here
14326
15047
  parseSimpleBinding(input, location, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
14327
15048
  const ast = this._parseBindingAst(input, location, absoluteOffset, interpolationConfig);
14328
15049
  const errors = this.checkSimpleExpression(ast);
@@ -14405,7 +15126,7 @@ class Parser$1 {
14405
15126
  }
14406
15127
  createInterpolationAst(strings, expressions, input, location, absoluteOffset) {
14407
15128
  const span = new ParseSpan(0, input.length);
14408
- const interpolation = new Interpolation(span, span.toAbsolute(absoluteOffset), strings, expressions);
15129
+ const interpolation = new Interpolation$1(span, span.toAbsolute(absoluteOffset), strings, expressions);
14409
15130
  return new ASTWithSource(interpolation, input, location, absoluteOffset, this.errors);
14410
15131
  }
14411
15132
  /**
@@ -19532,9 +20253,12 @@ class _TreeBuilder {
19532
20253
  }
19533
20254
  _consumeComment(token) {
19534
20255
  const text = this._advanceIf(7 /* TokenType.RAW_TEXT */);
19535
- this._advanceIf(11 /* TokenType.COMMENT_END */);
20256
+ const endToken = this._advanceIf(11 /* TokenType.COMMENT_END */);
19536
20257
  const value = text != null ? text.parts[0].trim() : null;
19537
- this._addToParent(new Comment(value, token.sourceSpan));
20258
+ const sourceSpan = endToken == null ?
20259
+ token.sourceSpan :
20260
+ new ParseSourceSpan(token.sourceSpan.start, endToken.sourceSpan.end, token.sourceSpan.fullStart);
20261
+ this._addToParent(new Comment(value, sourceSpan));
19538
20262
  }
19539
20263
  _consumeExpansion(token) {
19540
20264
  const switchValue = this._advance();
@@ -22525,7 +23249,7 @@ function createComponentDefConsts() {
22525
23249
  };
22526
23250
  }
22527
23251
  class TemplateDefinitionBuilder {
22528
- constructor(constantPool, parentBindingScope, level = 0, contextName, i18nContext, templateIndex, templateName, _namespace, relativeContextFilePath, i18nUseExternalIds, _constants = createComponentDefConsts()) {
23252
+ constructor(constantPool, parentBindingScope, level = 0, contextName, i18nContext, templateIndex, templateName, _namespace, relativeContextFilePath, i18nUseExternalIds, deferBlocks, _constants = createComponentDefConsts()) {
22529
23253
  this.constantPool = constantPool;
22530
23254
  this.level = level;
22531
23255
  this.contextName = contextName;
@@ -22534,6 +23258,7 @@ class TemplateDefinitionBuilder {
22534
23258
  this.templateName = templateName;
22535
23259
  this._namespace = _namespace;
22536
23260
  this.i18nUseExternalIds = i18nUseExternalIds;
23261
+ this.deferBlocks = deferBlocks;
22537
23262
  this._constants = _constants;
22538
23263
  this._dataIndex = 0;
22539
23264
  this._bindingContext = 0;
@@ -22736,7 +23461,7 @@ class TemplateDefinitionBuilder {
22736
23461
  else {
22737
23462
  const value = prop.value.visit(this._valueConverter);
22738
23463
  this.allocateBindingSlots(value);
22739
- if (value instanceof Interpolation) {
23464
+ if (value instanceof Interpolation$1) {
22740
23465
  const { strings, expressions } = value;
22741
23466
  const { id, bindings } = this.i18n;
22742
23467
  const label = assembleI18nBoundString(strings, bindings.size, id);
@@ -22856,7 +23581,7 @@ class TemplateDefinitionBuilder {
22856
23581
  const message = attr.i18n;
22857
23582
  const converted = attr.value.visit(this._valueConverter);
22858
23583
  this.allocateBindingSlots(converted);
22859
- if (converted instanceof Interpolation) {
23584
+ if (converted instanceof Interpolation$1) {
22860
23585
  const placeholders = assembleBoundTextPlaceholders(message);
22861
23586
  const params = placeholdersToParams(placeholders);
22862
23587
  i18nAttrArgs.push(literal(attr.name), this.i18nTranslate(message, params));
@@ -23076,7 +23801,7 @@ class TemplateDefinitionBuilder {
23076
23801
  }
23077
23802
  this.allocateBindingSlots(value);
23078
23803
  if (inputType === 0 /* BindingType.Property */) {
23079
- if (value instanceof Interpolation) {
23804
+ if (value instanceof Interpolation$1) {
23080
23805
  // prop="{{value}}" and friends
23081
23806
  this.interpolatedUpdateInstruction(getPropertyInterpolationExpression(value), elementIndex, attrName, input, value, params);
23082
23807
  }
@@ -23090,12 +23815,12 @@ class TemplateDefinitionBuilder {
23090
23815
  }
23091
23816
  }
23092
23817
  else if (inputType === 1 /* BindingType.Attribute */) {
23093
- if (value instanceof Interpolation && getInterpolationArgsLength(value) > 1) {
23818
+ if (value instanceof Interpolation$1 && getInterpolationArgsLength(value) > 1) {
23094
23819
  // attr.name="text{{value}}" and friends
23095
23820
  this.interpolatedUpdateInstruction(getAttributeInterpolationExpression(value), elementIndex, attrName, input, value, params);
23096
23821
  }
23097
23822
  else {
23098
- const boundValue = value instanceof Interpolation ? value.expressions[0] : value;
23823
+ const boundValue = value instanceof Interpolation$1 ? value.expressions[0] : value;
23099
23824
  // [attr.name]="value" or attr.name="{{value}}"
23100
23825
  // Collect the attribute bindings so that they can be chained at the end.
23101
23826
  attributeBindings.push({
@@ -23165,7 +23890,7 @@ class TemplateDefinitionBuilder {
23165
23890
  parameters.push(importExpr(Identifiers.templateRefExtractor));
23166
23891
  }
23167
23892
  // Create the template function
23168
- const templateVisitor = new TemplateDefinitionBuilder(this.constantPool, this._bindingScope, this.level + 1, contextName, this.i18n, templateIndex, templateName, this._namespace, this.fileBasedI18nSuffix, this.i18nUseExternalIds, this._constants);
23893
+ const templateVisitor = new TemplateDefinitionBuilder(this.constantPool, this._bindingScope, this.level + 1, contextName, this.i18n, templateIndex, templateName, this._namespace, this.fileBasedI18nSuffix, this.i18nUseExternalIds, this.deferBlocks, this._constants);
23169
23894
  // Nested templates must not be visited until after their parent templates have completed
23170
23895
  // processing, so they are queued here until after the initial pass. Otherwise, we wouldn't
23171
23896
  // be able to support bindings in nested templates to local refs that occur after the
@@ -23208,7 +23933,7 @@ class TemplateDefinitionBuilder {
23208
23933
  if (this.i18n) {
23209
23934
  const value = text.value.visit(this._valueConverter);
23210
23935
  this.allocateBindingSlots(value);
23211
- if (value instanceof Interpolation) {
23936
+ if (value instanceof Interpolation$1) {
23212
23937
  this.i18n.appendBoundText(text.i18n);
23213
23938
  this.i18nAppendBindings(value.expressions);
23214
23939
  }
@@ -23218,7 +23943,7 @@ class TemplateDefinitionBuilder {
23218
23943
  this.creationInstruction(text.sourceSpan, Identifiers.text, [literal(nodeIndex)]);
23219
23944
  const value = text.value.visit(this._valueConverter);
23220
23945
  this.allocateBindingSlots(value);
23221
- if (value instanceof Interpolation) {
23946
+ if (value instanceof Interpolation$1) {
23222
23947
  this.updateInstructionWithAdvance(nodeIndex, text.sourceSpan, getTextInterpolationExpression(value), () => this.getUpdateInstructionArguments(value));
23223
23948
  }
23224
23949
  else {
@@ -23275,8 +24000,43 @@ class TemplateDefinitionBuilder {
23275
24000
  }
23276
24001
  return null;
23277
24002
  }
23278
- // TODO: implement deferred block instructions.
23279
- visitDeferredBlock(deferred) { }
24003
+ visitDeferredBlock(deferred) {
24004
+ const templateIndex = this.allocateDataSlot();
24005
+ const deferredDeps = this.deferBlocks.get(deferred);
24006
+ const contextName = `${this.contextName}_Defer_${templateIndex}`;
24007
+ const depsFnName = `${contextName}_DepsFn`;
24008
+ const parameters = [
24009
+ literal(templateIndex),
24010
+ deferredDeps ? variable(depsFnName) : TYPED_NULL_EXPR,
24011
+ ];
24012
+ if (deferredDeps) {
24013
+ // This defer block has deps for which we need to generate dynamic imports.
24014
+ const dependencyExp = [];
24015
+ for (const deferredDep of deferredDeps) {
24016
+ if (deferredDep.isDeferrable) {
24017
+ // Callback function, e.g. `function(m) { return m.MyCmp; }`.
24018
+ const innerFn = fn([new FnParam('m', DYNAMIC_TYPE)], [new ReturnStatement(variable('m').prop(deferredDep.symbolName))]);
24019
+ const fileName = deferredDep.importPath;
24020
+ // Dynamic import, e.g. `import('./a').then(...)`.
24021
+ const importExpr = (new DynamicImportExpr(fileName)).prop('then').callFn([innerFn]);
24022
+ dependencyExp.push(importExpr);
24023
+ }
24024
+ else {
24025
+ // Non-deferrable symbol, just use a reference to the type.
24026
+ dependencyExp.push(deferredDep.type);
24027
+ }
24028
+ }
24029
+ const depsFnBody = [];
24030
+ depsFnBody.push(new ReturnStatement(literalArr(dependencyExp)));
24031
+ const depsFnExpr = fn([] /* args */, depsFnBody, INFERRED_TYPE, null, depsFnName);
24032
+ this.constantPool.statements.push(depsFnExpr.toDeclStmt(depsFnName));
24033
+ }
24034
+ // e.g. `defer(1, MyComp_Defer_1_DepsFn, ...)`
24035
+ this.creationInstruction(deferred.sourceSpan, Identifiers.defer, () => {
24036
+ return trimTrailingNulls(parameters);
24037
+ });
24038
+ }
24039
+ // TODO: implement nested deferred block instructions.
23280
24040
  visitDeferredTrigger(trigger) { }
23281
24041
  visitDeferredBlockPlaceholder(block) { }
23282
24042
  visitDeferredBlockError(block) { }
@@ -23312,7 +24072,7 @@ class TemplateDefinitionBuilder {
23312
24072
  continue;
23313
24073
  }
23314
24074
  this.allocateBindingSlots(value);
23315
- if (value instanceof Interpolation) {
24075
+ if (value instanceof Interpolation$1) {
23316
24076
  // Params typically contain attribute namespace and value sanitizer, which is applicable
23317
24077
  // for regular HTML elements, but not applicable for <ng-template> (since props act as
23318
24078
  // inputs to directives), so keep params array empty.
@@ -23344,7 +24104,7 @@ class TemplateDefinitionBuilder {
23344
24104
  if (instruction) {
23345
24105
  for (const call of instruction.calls) {
23346
24106
  allocateBindingSlots += call.allocateBindingSlots;
23347
- this.updateInstructionWithAdvance(elementIndex, call.sourceSpan, instruction.reference, () => call.params(value => (call.supportsInterpolation && value instanceof Interpolation) ?
24107
+ this.updateInstructionWithAdvance(elementIndex, call.sourceSpan, instruction.reference, () => call.params(value => (call.supportsInterpolation && value instanceof Interpolation$1) ?
23348
24108
  this.getUpdateInstructionArguments(value) :
23349
24109
  this.convertPropertyBinding(value)));
23350
24110
  }
@@ -23377,7 +24137,7 @@ class TemplateDefinitionBuilder {
23377
24137
  return originalSlots;
23378
24138
  }
23379
24139
  allocateBindingSlots(value) {
23380
- this._bindingSlots += value instanceof Interpolation ? value.expressions.length : 1;
24140
+ this._bindingSlots += value instanceof Interpolation$1 ? value.expressions.length : 1;
23381
24141
  }
23382
24142
  /**
23383
24143
  * Gets an expression that refers to the implicit receiver. The implicit
@@ -24330,7 +25090,7 @@ function compileComponentFromMetadata(meta, constantPool, bindingParser) {
24330
25090
  // This is the main path currently used in compilation, which compiles the template with the
24331
25091
  // legacy `TemplateDefinitionBuilder`.
24332
25092
  const template = meta.template;
24333
- const templateBuilder = new TemplateDefinitionBuilder(constantPool, BindingScope.createRootScope(), 0, templateTypeName, null, null, templateName, Identifiers.namespaceHTML, meta.relativeContextFilePath, meta.i18nUseExternalIds);
25093
+ const templateBuilder = new TemplateDefinitionBuilder(constantPool, BindingScope.createRootScope(), 0, templateTypeName, null, null, templateName, Identifiers.namespaceHTML, meta.relativeContextFilePath, meta.i18nUseExternalIds, meta.deferBlocks);
24334
25094
  const templateFunctionExpression = templateBuilder.buildTemplateFunction(template.nodes, []);
24335
25095
  // We need to provide this so that dynamically generated components know what
24336
25096
  // projected content blocks to pass through to the component when it is
@@ -24365,7 +25125,7 @@ function compileComponentFromMetadata(meta, constantPool, bindingParser) {
24365
25125
  else {
24366
25126
  // This path compiles the template using the prototype template pipeline. First the template is
24367
25127
  // ingested into IR:
24368
- const tpl = ingest(meta.name, meta.template.nodes, constantPool);
25128
+ const tpl = ingestComponent(meta.name, meta.template.nodes, constantPool);
24369
25129
  // Then the IR is transformed to prepare it for cod egeneration.
24370
25130
  transformTemplate(tpl);
24371
25131
  // Finally we emit the template function:
@@ -24594,6 +25354,25 @@ function createViewQueriesFunction(viewQueries, constantPool, name) {
24594
25354
  }
24595
25355
  // Return a host binding function or null if one is not necessary.
24596
25356
  function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindingParser, constantPool, selector, name, definitionMap) {
25357
+ const bindings = bindingParser.createBoundHostProperties(hostBindingsMetadata.properties, typeSourceSpan);
25358
+ // Calculate host event bindings
25359
+ const eventBindings = bindingParser.createDirectiveHostEventAsts(hostBindingsMetadata.listeners, typeSourceSpan);
25360
+ if (USE_TEMPLATE_PIPELINE) {
25361
+ // TODO: host binding metadata is not yet parsed in the template pipeline, so we need to extract
25362
+ // that code from below. Then, we will ingest a `HostBindingJob`, and run the template pipeline
25363
+ // phases.
25364
+ const hostJob = ingestHostBinding({
25365
+ componentName: name,
25366
+ properties: bindings,
25367
+ events: eventBindings,
25368
+ }, bindingParser, constantPool);
25369
+ transformHostBinding(hostJob);
25370
+ const varCount = hostJob.root.vars;
25371
+ if (varCount !== null && varCount > 0) {
25372
+ definitionMap.set('hostVars', literal(varCount));
25373
+ }
25374
+ return emitHostBindingFunction(hostJob);
25375
+ }
24597
25376
  const bindingContext = variable(CONTEXT_NAME);
24598
25377
  const styleBuilder = new StylingBuilder(bindingContext);
24599
25378
  const { styleAttr, classAttr } = hostBindingsMetadata.specialAttributes;
@@ -24607,13 +25386,10 @@ function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindin
24607
25386
  const updateInstructions = [];
24608
25387
  const updateVariables = [];
24609
25388
  const hostBindingSourceSpan = typeSourceSpan;
24610
- // Calculate host event bindings
24611
- const eventBindings = bindingParser.createDirectiveHostEventAsts(hostBindingsMetadata.listeners, hostBindingSourceSpan);
24612
25389
  if (eventBindings && eventBindings.length) {
24613
25390
  createInstructions.push(...createHostListeners(eventBindings, name));
24614
25391
  }
24615
25392
  // Calculate the host property bindings
24616
- const bindings = bindingParser.createBoundHostProperties(hostBindingsMetadata.properties, hostBindingSourceSpan);
24617
25393
  const allOtherBindings = [];
24618
25394
  // We need to calculate the total amount of binding slots required by
24619
25395
  // all the instructions together before any value conversions happen.
@@ -24956,6 +25732,11 @@ function createHostDirectivesMappingArray(mapping) {
24956
25732
  class ResourceLoader {
24957
25733
  }
24958
25734
 
25735
+ let enabledBlockTypes;
25736
+ /** Temporary utility that enables specific block types in JIT compilations. */
25737
+ function ɵsetEnabledBlockTypes(types) {
25738
+ enabledBlockTypes = types.length > 0 ? new Set(types) : undefined;
25739
+ }
24959
25740
  class CompilerFacadeImpl {
24960
25741
  constructor(jitEvaluator = new JitEvaluator()) {
24961
25742
  this.jitEvaluator = jitEvaluator;
@@ -25076,6 +25857,10 @@ class CompilerFacadeImpl {
25076
25857
  template,
25077
25858
  declarations: facade.declarations.map(convertDeclarationFacadeToMetadata),
25078
25859
  declarationListEmitMode: 0 /* DeclarationListEmitMode.Direct */,
25860
+ // TODO: leaving empty in JIT mode for now,
25861
+ // to be implemented as one of the next steps.
25862
+ deferBlocks: new Map(),
25863
+ deferrableDeclToImportDecl: new Map(),
25079
25864
  styles: [...facade.styles, ...template.styles],
25080
25865
  encapsulation: facade.encapsulation,
25081
25866
  interpolation,
@@ -25306,6 +26091,10 @@ function convertDeclareComponentFacadeToMetadata(decl, typeSourceSpan, sourceMap
25306
26091
  viewProviders: decl.viewProviders !== undefined ? new WrappedNodeExpr(decl.viewProviders) :
25307
26092
  null,
25308
26093
  animations: decl.animations !== undefined ? new WrappedNodeExpr(decl.animations) : null,
26094
+ // TODO: leaving empty in JIT mode for now,
26095
+ // to be implemented as one of the next steps.
26096
+ deferBlocks: new Map(),
26097
+ deferrableDeclToImportDecl: new Map(),
25309
26098
  changeDetection: decl.changeDetection ?? ChangeDetectionStrategy.Default,
25310
26099
  encapsulation: decl.encapsulation ?? ViewEncapsulation.Emulated,
25311
26100
  interpolation,
@@ -25353,11 +26142,7 @@ function convertPipeDeclarationToMetadata(pipe) {
25353
26142
  function parseJitTemplate(template, typeName, sourceMapUrl, preserveWhitespaces, interpolation) {
25354
26143
  const interpolationConfig = interpolation ? InterpolationConfig.fromArray(interpolation) : DEFAULT_INTERPOLATION_CONFIG;
25355
26144
  // Parse the template and check for errors.
25356
- const parsed = parseTemplate(template, sourceMapUrl, {
25357
- preserveWhitespaces,
25358
- interpolationConfig,
25359
- enabledBlockTypes: new Set(), // TODO: enable deferred blocks when testing in JIT mode.
25360
- });
26145
+ const parsed = parseTemplate(template, sourceMapUrl, { preserveWhitespaces, interpolationConfig, enabledBlockTypes });
25361
26146
  if (parsed.errors !== null) {
25362
26147
  const errors = parsed.errors.map(err => err.toString()).join(', ');
25363
26148
  throw new Error(`Errors during JIT compilation of template for ${typeName}: ${errors}`);
@@ -25546,7 +26331,7 @@ function publishFacade(global) {
25546
26331
  * @description
25547
26332
  * Entry point for all public APIs of the compiler package.
25548
26333
  */
25549
- const VERSION = new Version('16.2.0-next.4');
26334
+ const VERSION = new Version('16.2.0');
25550
26335
 
25551
26336
  class CompilerConfig {
25552
26337
  constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, useJit = true, missingTranslation = null, preserveWhitespaces, strictInjectionParameters } = {}) {
@@ -27014,11 +27799,11 @@ class R3TargetBinder {
27014
27799
  // - bindings: Map of inputs, outputs, and attributes to the directive/element that claims
27015
27800
  // them. TODO(alxhub): handle multiple directives claiming an input/output/etc.
27016
27801
  // - references: Map of #references to their targets.
27017
- const { directives, bindings, references } = DirectiveBinder.apply(target.template, this.directiveMatcher);
27802
+ const { directives, eagerDirectives, bindings, references } = DirectiveBinder.apply(target.template, this.directiveMatcher);
27018
27803
  // Finally, run the TemplateBinder to bind references, variables, and other entities within the
27019
27804
  // template. This extracts all the metadata that doesn't depend on directive matching.
27020
- const { expressions, symbols, nestingLevel, usedPipes } = TemplateBinder.applyWithScope(target.template, scope);
27021
- return new R3BoundTarget(target, directives, bindings, references, expressions, symbols, nestingLevel, templateEntities, usedPipes);
27805
+ const { expressions, symbols, nestingLevel, usedPipes, eagerPipes, deferBlocks } = TemplateBinder.applyWithScope(target.template, scope);
27806
+ return new R3BoundTarget(target, directives, eagerDirectives, bindings, references, expressions, symbols, nestingLevel, templateEntities, usedPipes, eagerPipes, deferBlocks);
27022
27807
  }
27023
27808
  }
27024
27809
  /**
@@ -27159,11 +27944,14 @@ class Scope {
27159
27944
  * Usually used via the static `apply()` method.
27160
27945
  */
27161
27946
  class DirectiveBinder {
27162
- constructor(matcher, directives, bindings, references) {
27947
+ constructor(matcher, directives, eagerDirectives, bindings, references) {
27163
27948
  this.matcher = matcher;
27164
27949
  this.directives = directives;
27950
+ this.eagerDirectives = eagerDirectives;
27165
27951
  this.bindings = bindings;
27166
27952
  this.references = references;
27953
+ // Indicates whether we are visiting elements within a {#defer} block
27954
+ this.isInDeferBlock = false;
27167
27955
  }
27168
27956
  /**
27169
27957
  * Process a template (list of `Node`s) and perform directive matching against each node.
@@ -27181,9 +27969,10 @@ class DirectiveBinder {
27181
27969
  const directives = new Map();
27182
27970
  const bindings = new Map();
27183
27971
  const references = new Map();
27184
- const matcher = new DirectiveBinder(selectorMatcher, directives, bindings, references);
27972
+ const eagerDirectives = [];
27973
+ const matcher = new DirectiveBinder(selectorMatcher, directives, eagerDirectives, bindings, references);
27185
27974
  matcher.ingest(template);
27186
- return { directives, bindings, references };
27975
+ return { directives, eagerDirectives, bindings, references };
27187
27976
  }
27188
27977
  ingest(template) {
27189
27978
  template.forEach(node => node.visit(this));
@@ -27203,6 +27992,9 @@ class DirectiveBinder {
27203
27992
  this.matcher.match(cssSelector, (_selector, results) => directives.push(...results));
27204
27993
  if (directives.length > 0) {
27205
27994
  this.directives.set(node, directives);
27995
+ if (!this.isInDeferBlock) {
27996
+ this.eagerDirectives.push(...directives);
27997
+ }
27206
27998
  }
27207
27999
  // Resolve any references that are created on this node.
27208
28000
  node.references.forEach(ref => {
@@ -27253,7 +28045,9 @@ class DirectiveBinder {
27253
28045
  node.children.forEach(child => child.visit(this));
27254
28046
  }
27255
28047
  visitDeferredBlock(deferred) {
28048
+ this.isInDeferBlock = true;
27256
28049
  deferred.children.forEach(child => child.visit(this));
28050
+ this.isInDeferBlock = false;
27257
28051
  deferred.placeholder?.visit(this);
27258
28052
  deferred.loading?.visit(this);
27259
28053
  deferred.error?.visit(this);
@@ -27290,15 +28084,19 @@ class DirectiveBinder {
27290
28084
  * by overridden methods from that visitor.
27291
28085
  */
27292
28086
  class TemplateBinder extends RecursiveAstVisitor {
27293
- constructor(bindings, symbols, usedPipes, nestingLevel, scope, template, level) {
28087
+ constructor(bindings, symbols, usedPipes, eagerPipes, deferBlocks, nestingLevel, scope, template, level) {
27294
28088
  super();
27295
28089
  this.bindings = bindings;
27296
28090
  this.symbols = symbols;
27297
28091
  this.usedPipes = usedPipes;
28092
+ this.eagerPipes = eagerPipes;
28093
+ this.deferBlocks = deferBlocks;
27298
28094
  this.nestingLevel = nestingLevel;
27299
28095
  this.scope = scope;
27300
28096
  this.template = template;
27301
28097
  this.level = level;
28098
+ // Indicates whether we are visiting elements within a {#defer} block
28099
+ this.isInDeferBlock = false;
27302
28100
  // Save a bit of processing time by constructing this closure in advance.
27303
28101
  this.visitNode = (node) => node.visit(this);
27304
28102
  }
@@ -27330,11 +28128,13 @@ class TemplateBinder extends RecursiveAstVisitor {
27330
28128
  const symbols = new Map();
27331
28129
  const nestingLevel = new Map();
27332
28130
  const usedPipes = new Set();
28131
+ const eagerPipes = new Set();
27333
28132
  const template = nodes instanceof Template ? nodes : null;
28133
+ const deferBlocks = new Set();
27334
28134
  // The top-level template has nesting level 0.
27335
- const binder = new TemplateBinder(expressions, symbols, usedPipes, nestingLevel, scope, template, 0);
28135
+ const binder = new TemplateBinder(expressions, symbols, usedPipes, eagerPipes, deferBlocks, nestingLevel, scope, template, 0);
27336
28136
  binder.ingest(nodes);
27337
- return { expressions, symbols, nestingLevel, usedPipes };
28137
+ return { expressions, symbols, nestingLevel, usedPipes, eagerPipes, deferBlocks };
27338
28138
  }
27339
28139
  ingest(template) {
27340
28140
  if (template instanceof Template) {
@@ -27365,7 +28165,7 @@ class TemplateBinder extends RecursiveAstVisitor {
27365
28165
  template.references.forEach(this.visitNode);
27366
28166
  // Next, recurse into the template using its scope, and bumping the nesting level up by one.
27367
28167
  const childScope = this.scope.getChildScope(template);
27368
- const binder = new TemplateBinder(this.bindings, this.symbols, this.usedPipes, this.nestingLevel, childScope, template, this.level + 1);
28168
+ const binder = new TemplateBinder(this.bindings, this.symbols, this.usedPipes, this.eagerPipes, this.deferBlocks, this.nestingLevel, childScope, template, this.level + 1);
27369
28169
  binder.ingest(template);
27370
28170
  }
27371
28171
  visitVariable(variable) {
@@ -27396,9 +28196,12 @@ class TemplateBinder extends RecursiveAstVisitor {
27396
28196
  event.handler.visit(this);
27397
28197
  }
27398
28198
  visitDeferredBlock(deferred) {
28199
+ this.deferBlocks.add(deferred);
28200
+ this.isInDeferBlock = true;
28201
+ deferred.children.forEach(this.visitNode);
28202
+ this.isInDeferBlock = false;
27399
28203
  deferred.triggers.forEach(this.visitNode);
27400
28204
  deferred.prefetchTriggers.forEach(this.visitNode);
27401
- deferred.children.forEach(this.visitNode);
27402
28205
  deferred.placeholder && this.visitNode(deferred.placeholder);
27403
28206
  deferred.loading && this.visitNode(deferred.loading);
27404
28207
  deferred.error && this.visitNode(deferred.error);
@@ -27422,6 +28225,9 @@ class TemplateBinder extends RecursiveAstVisitor {
27422
28225
  }
27423
28226
  visitPipe(ast, context) {
27424
28227
  this.usedPipes.add(ast.name);
28228
+ if (!this.isInDeferBlock) {
28229
+ this.eagerPipes.add(ast.name);
28230
+ }
27425
28231
  return super.visitPipe(ast, context);
27426
28232
  }
27427
28233
  // These five types of AST expressions can refer to expression roots, which could be variables
@@ -27458,9 +28264,10 @@ class TemplateBinder extends RecursiveAstVisitor {
27458
28264
  * See `BoundTarget` for documentation on the individual methods.
27459
28265
  */
27460
28266
  class R3BoundTarget {
27461
- constructor(target, directives, bindings, references, exprTargets, symbols, nestingLevel, templateEntities, usedPipes) {
28267
+ constructor(target, directives, eagerDirectives, bindings, references, exprTargets, symbols, nestingLevel, templateEntities, usedPipes, eagerPipes, deferredBlocks) {
27462
28268
  this.target = target;
27463
28269
  this.directives = directives;
28270
+ this.eagerDirectives = eagerDirectives;
27464
28271
  this.bindings = bindings;
27465
28272
  this.references = references;
27466
28273
  this.exprTargets = exprTargets;
@@ -27468,6 +28275,8 @@ class R3BoundTarget {
27468
28275
  this.nestingLevel = nestingLevel;
27469
28276
  this.templateEntities = templateEntities;
27470
28277
  this.usedPipes = usedPipes;
28278
+ this.eagerPipes = eagerPipes;
28279
+ this.deferredBlocks = deferredBlocks;
27471
28280
  }
27472
28281
  getEntitiesInTemplateScope(template) {
27473
28282
  return this.templateEntities.get(template) ?? new Set();
@@ -27495,9 +28304,19 @@ class R3BoundTarget {
27495
28304
  this.directives.forEach(dirs => dirs.forEach(dir => set.add(dir)));
27496
28305
  return Array.from(set.values());
27497
28306
  }
28307
+ getEagerlyUsedDirectives() {
28308
+ const set = new Set(this.eagerDirectives);
28309
+ return Array.from(set.values());
28310
+ }
27498
28311
  getUsedPipes() {
27499
28312
  return Array.from(this.usedPipes);
27500
28313
  }
28314
+ getEagerlyUsedPipes() {
28315
+ return Array.from(this.eagerPipes);
28316
+ }
28317
+ getDeferBlocks() {
28318
+ return Array.from(this.deferredBlocks);
28319
+ }
27501
28320
  }
27502
28321
  function extractTemplateEntities(rootScope) {
27503
28322
  const entityMap = new Map();
@@ -27555,7 +28374,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
27555
28374
  function compileDeclareClassMetadata(metadata) {
27556
28375
  const definitionMap = new DefinitionMap();
27557
28376
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
27558
- definitionMap.set('version', literal('16.2.0-next.4'));
28377
+ definitionMap.set('version', literal('16.2.0'));
27559
28378
  definitionMap.set('ngImport', importExpr(Identifiers.core));
27560
28379
  definitionMap.set('type', metadata.type);
27561
28380
  definitionMap.set('decorators', metadata.decorators);
@@ -27658,7 +28477,7 @@ function compileDeclareDirectiveFromMetadata(meta) {
27658
28477
  function createDirectiveDefinitionMap(meta) {
27659
28478
  const definitionMap = new DefinitionMap();
27660
28479
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
27661
- definitionMap.set('version', literal('16.2.0-next.4'));
28480
+ definitionMap.set('version', literal('16.2.0'));
27662
28481
  // e.g. `type: MyDirective`
27663
28482
  definitionMap.set('type', meta.type.value);
27664
28483
  if (meta.isStandalone) {
@@ -27886,7 +28705,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
27886
28705
  function compileDeclareFactoryFunction(meta) {
27887
28706
  const definitionMap = new DefinitionMap();
27888
28707
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
27889
- definitionMap.set('version', literal('16.2.0-next.4'));
28708
+ definitionMap.set('version', literal('16.2.0'));
27890
28709
  definitionMap.set('ngImport', importExpr(Identifiers.core));
27891
28710
  definitionMap.set('type', meta.type.value);
27892
28711
  definitionMap.set('deps', compileDependencies(meta.deps));
@@ -27921,7 +28740,7 @@ function compileDeclareInjectableFromMetadata(meta) {
27921
28740
  function createInjectableDefinitionMap(meta) {
27922
28741
  const definitionMap = new DefinitionMap();
27923
28742
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
27924
- definitionMap.set('version', literal('16.2.0-next.4'));
28743
+ definitionMap.set('version', literal('16.2.0'));
27925
28744
  definitionMap.set('ngImport', importExpr(Identifiers.core));
27926
28745
  definitionMap.set('type', meta.type.value);
27927
28746
  // Only generate providedIn property if it has a non-null value
@@ -27972,7 +28791,7 @@ function compileDeclareInjectorFromMetadata(meta) {
27972
28791
  function createInjectorDefinitionMap(meta) {
27973
28792
  const definitionMap = new DefinitionMap();
27974
28793
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
27975
- definitionMap.set('version', literal('16.2.0-next.4'));
28794
+ definitionMap.set('version', literal('16.2.0'));
27976
28795
  definitionMap.set('ngImport', importExpr(Identifiers.core));
27977
28796
  definitionMap.set('type', meta.type.value);
27978
28797
  definitionMap.set('providers', meta.providers);
@@ -28005,7 +28824,7 @@ function createNgModuleDefinitionMap(meta) {
28005
28824
  throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
28006
28825
  }
28007
28826
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
28008
- definitionMap.set('version', literal('16.2.0-next.4'));
28827
+ definitionMap.set('version', literal('16.2.0'));
28009
28828
  definitionMap.set('ngImport', importExpr(Identifiers.core));
28010
28829
  definitionMap.set('type', meta.type.value);
28011
28830
  // We only generate the keys in the metadata if the arrays contain values.
@@ -28056,7 +28875,7 @@ function compileDeclarePipeFromMetadata(meta) {
28056
28875
  function createPipeDefinitionMap(meta) {
28057
28876
  const definitionMap = new DefinitionMap();
28058
28877
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
28059
- definitionMap.set('version', literal('16.2.0-next.4'));
28878
+ definitionMap.set('version', literal('16.2.0'));
28060
28879
  definitionMap.set('ngImport', importExpr(Identifiers.core));
28061
28880
  // e.g. `type: MyPipe`
28062
28881
  definitionMap.set('type', meta.type.value);
@@ -28089,5 +28908,5 @@ publishFacade(_global);
28089
28908
 
28090
28909
  // This file is not used to build this module. It is only used during editing
28091
28910
 
28092
- export { AST, ASTWithName, ASTWithSource, AbsoluteSourceSpan, ArrayType, AstMemoryEfficientTransformer, AstTransformer, Attribute, Binary, BinaryOperator, BinaryOperatorExpr, BindingPipe, Block, BlockGroup, BlockParameter, BoundElementProperty, BuiltinType, BuiltinTypeName, CUSTOM_ELEMENTS_SCHEMA, Call, Chain, ChangeDetectionStrategy, CommaExpr, Comment, CompilerConfig, Conditional, ConditionalExpr, ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DYNAMIC_TYPE, DeclareFunctionStmt, DeclareVarStmt, DomElementSchemaRegistry, DynamicImportExpr, EOF, Element, ElementSchemaRegistry, EmitterVisitorContext, EmptyExpr$1 as EmptyExpr, Expansion, ExpansionCase, Expression, ExpressionBinding, ExpressionStatement, ExpressionType, ExternalExpr, ExternalReference, FactoryTarget$1 as FactoryTarget, FunctionExpr, HtmlParser, HtmlTagDefinition, I18NHtmlParser, IfStmt, ImplicitReceiver, InstantiateExpr, Interpolation, InterpolationConfig, InvokeFunctionExpr, JSDocComment, JitEvaluator, KeyedRead, KeyedWrite, LeadingComment, Lexer, LiteralArray, LiteralArrayExpr, LiteralExpr, LiteralMap, LiteralMapExpr, LiteralPrimitive, LocalizedString, MapType, MessageBundle, NONE_TYPE, NO_ERRORS_SCHEMA, NodeWithI18n, NonNullAssert, NotExpr, ParseError, ParseErrorLevel, ParseLocation, ParseSourceFile, ParseSourceSpan, ParseSpan, ParseTreeResult, ParsedEvent, ParsedProperty, ParsedPropertyType, ParsedVariable, Parser$1 as Parser, ParserError, PrefixNot, PropertyRead, PropertyWrite, R3BoundTarget, Identifiers as R3Identifiers, R3NgModuleMetadataKind, R3SelectorScopeMode, R3TargetBinder, R3TemplateDependencyKind, ReadKeyExpr, ReadPropExpr, ReadVarExpr, RecursiveAstVisitor, RecursiveVisitor, ResourceLoader, ReturnStatement, STRING_TYPE, SafeCall, SafeKeyedRead, SafePropertyRead, SelectorContext, SelectorListContext, SelectorMatcher, Serializer, SplitInterpolation, Statement, StmtModifier, TagContentType, TaggedTemplateExpr, TemplateBindingParseResult, TemplateLiteral, TemplateLiteralElement, Text, ThisReceiver, BoundAttribute as TmplAstBoundAttribute, BoundDeferredTrigger as TmplAstBoundDeferredTrigger, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Content as TmplAstContent, DeferredBlock as TmplAstDeferredBlock, DeferredBlockError as TmplAstDeferredBlockError, DeferredBlockLoading as TmplAstDeferredBlockLoading, DeferredBlockPlaceholder as TmplAstDeferredBlockPlaceholder, DeferredTrigger as TmplAstDeferredTrigger, Element$1 as TmplAstElement, HoverDeferredTrigger as TmplAstHoverDeferredTrigger, Icu$1 as TmplAstIcu, IdleDeferredTrigger as TmplAstIdleDeferredTrigger, ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger, InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger, RecursiveVisitor$1 as TmplAstRecursiveVisitor, Reference as TmplAstReference, Template as TmplAstTemplate, Text$3 as TmplAstText, TextAttribute as TmplAstTextAttribute, TimerDeferredTrigger as TmplAstTimerDeferredTrigger, Variable as TmplAstVariable, ViewportDeferredTrigger as TmplAstViewportDeferredTrigger, Token, TokenType, TransplantedType, TreeError, Type, TypeModifier, TypeofExpr, Unary, UnaryOperator, UnaryOperatorExpr, VERSION, VariableBinding, Version, ViewEncapsulation, WrappedNodeExpr, WriteKeyExpr, WritePropExpr, WriteVarExpr, Xliff, Xliff2, Xmb, XmlParser, Xtb, _ParseAST, compileClassMetadata, compileComponentFromMetadata, compileDeclareClassMetadata, compileDeclareComponentFromMetadata, compileDeclareDirectiveFromMetadata, compileDeclareFactoryFunction, compileDeclareInjectableFromMetadata, compileDeclareInjectorFromMetadata, compileDeclareNgModuleFromMetadata, compileDeclarePipeFromMetadata, compileDirectiveFromMetadata, compileFactoryFunction, compileInjectable, compileInjector, compileNgModule, compilePipeFromMetadata, computeMsgId, core, createInjectableType, createMayBeForwardRefExpression, devOnlyGuardedExpression, emitDistinctChangesOnlyDefaultValue, getHtmlTagDefinition, getNsPrefix, getSafePropertyAccessString, identifierName, isIdentifier, isNgContainer, isNgContent, isNgTemplate, jsDocComment, leadingComment, literalMap, makeBindingParser, mergeNsAndName, output_ast as outputAst, parseHostBindings, parseTemplate, preserveWhitespacesDefault, publishFacade, r3JitTypeSourceSpan, sanitizeIdentifier, splitNsName, verifyHostBindings, visitAll };
28911
+ export { AST, ASTWithName, ASTWithSource, AbsoluteSourceSpan, ArrayType, AstMemoryEfficientTransformer, AstTransformer, Attribute, Binary, BinaryOperator, BinaryOperatorExpr, BindingPipe, Block, BlockGroup, BlockParameter, BoundElementProperty, BuiltinType, BuiltinTypeName, CUSTOM_ELEMENTS_SCHEMA, Call, Chain, ChangeDetectionStrategy, CommaExpr, Comment, CompilerConfig, Conditional, ConditionalExpr, ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DYNAMIC_TYPE, DeclareFunctionStmt, DeclareVarStmt, DomElementSchemaRegistry, DynamicImportExpr, EOF, Element, ElementSchemaRegistry, EmitterVisitorContext, EmptyExpr$1 as EmptyExpr, Expansion, ExpansionCase, Expression, ExpressionBinding, ExpressionStatement, ExpressionType, ExternalExpr, ExternalReference, FactoryTarget$1 as FactoryTarget, FunctionExpr, HtmlParser, HtmlTagDefinition, I18NHtmlParser, IfStmt, ImplicitReceiver, InstantiateExpr, Interpolation$1 as Interpolation, InterpolationConfig, InvokeFunctionExpr, JSDocComment, JitEvaluator, KeyedRead, KeyedWrite, LeadingComment, Lexer, LiteralArray, LiteralArrayExpr, LiteralExpr, LiteralMap, LiteralMapExpr, LiteralPrimitive, LocalizedString, MapType, MessageBundle, NONE_TYPE, NO_ERRORS_SCHEMA, NodeWithI18n, NonNullAssert, NotExpr, ParseError, ParseErrorLevel, ParseLocation, ParseSourceFile, ParseSourceSpan, ParseSpan, ParseTreeResult, ParsedEvent, ParsedProperty, ParsedPropertyType, ParsedVariable, Parser$1 as Parser, ParserError, PrefixNot, PropertyRead, PropertyWrite, R3BoundTarget, Identifiers as R3Identifiers, R3NgModuleMetadataKind, R3SelectorScopeMode, R3TargetBinder, R3TemplateDependencyKind, ReadKeyExpr, ReadPropExpr, ReadVarExpr, RecursiveAstVisitor, RecursiveVisitor, ResourceLoader, ReturnStatement, STRING_TYPE, SafeCall, SafeKeyedRead, SafePropertyRead, SelectorContext, SelectorListContext, SelectorMatcher, Serializer, SplitInterpolation, Statement, StmtModifier, TagContentType, TaggedTemplateExpr, TemplateBindingParseResult, TemplateLiteral, TemplateLiteralElement, Text, ThisReceiver, BoundAttribute as TmplAstBoundAttribute, BoundDeferredTrigger as TmplAstBoundDeferredTrigger, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Content as TmplAstContent, DeferredBlock as TmplAstDeferredBlock, DeferredBlockError as TmplAstDeferredBlockError, DeferredBlockLoading as TmplAstDeferredBlockLoading, DeferredBlockPlaceholder as TmplAstDeferredBlockPlaceholder, DeferredTrigger as TmplAstDeferredTrigger, Element$1 as TmplAstElement, HoverDeferredTrigger as TmplAstHoverDeferredTrigger, Icu$1 as TmplAstIcu, IdleDeferredTrigger as TmplAstIdleDeferredTrigger, ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger, InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger, RecursiveVisitor$1 as TmplAstRecursiveVisitor, Reference as TmplAstReference, Template as TmplAstTemplate, Text$3 as TmplAstText, TextAttribute as TmplAstTextAttribute, TimerDeferredTrigger as TmplAstTimerDeferredTrigger, Variable as TmplAstVariable, ViewportDeferredTrigger as TmplAstViewportDeferredTrigger, Token, TokenType, TransplantedType, TreeError, Type, TypeModifier, TypeofExpr, Unary, UnaryOperator, UnaryOperatorExpr, VERSION, VariableBinding, Version, ViewEncapsulation, WrappedNodeExpr, WriteKeyExpr, WritePropExpr, WriteVarExpr, Xliff, Xliff2, Xmb, XmlParser, Xtb, _ParseAST, compileClassMetadata, compileComponentFromMetadata, compileDeclareClassMetadata, compileDeclareComponentFromMetadata, compileDeclareDirectiveFromMetadata, compileDeclareFactoryFunction, compileDeclareInjectableFromMetadata, compileDeclareInjectorFromMetadata, compileDeclareNgModuleFromMetadata, compileDeclarePipeFromMetadata, compileDirectiveFromMetadata, compileFactoryFunction, compileInjectable, compileInjector, compileNgModule, compilePipeFromMetadata, computeMsgId, core, createInjectableType, createMayBeForwardRefExpression, devOnlyGuardedExpression, emitDistinctChangesOnlyDefaultValue, getHtmlTagDefinition, getNsPrefix, getSafePropertyAccessString, identifierName, isIdentifier, isNgContainer, isNgContent, isNgTemplate, jsDocComment, leadingComment, literalMap, makeBindingParser, mergeNsAndName, output_ast as outputAst, parseHostBindings, parseTemplate, preserveWhitespacesDefault, publishFacade, r3JitTypeSourceSpan, sanitizeIdentifier, splitNsName, verifyHostBindings, visitAll };
28093
28912
  //# sourceMappingURL=compiler.mjs.map