@angular/compiler 16.2.0-next.3 → 16.2.0-rc.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.
- package/esm2022/src/expression_parser/parser.mjs +2 -1
- package/esm2022/src/jit_compiler_facade.mjs +15 -6
- package/esm2022/src/ml_parser/lexer.mjs +14 -3
- package/esm2022/src/ml_parser/parser.mjs +6 -3
- package/esm2022/src/output/output_ast.mjs +2 -2
- package/esm2022/src/render3/partial/class_metadata.mjs +1 -1
- package/esm2022/src/render3/partial/directive.mjs +1 -1
- package/esm2022/src/render3/partial/factory.mjs +1 -1
- package/esm2022/src/render3/partial/injectable.mjs +1 -1
- package/esm2022/src/render3/partial/injector.mjs +1 -1
- package/esm2022/src/render3/partial/ng_module.mjs +1 -1
- package/esm2022/src/render3/partial/pipe.mjs +1 -1
- package/esm2022/src/render3/r3_identifiers.mjs +2 -1
- package/esm2022/src/render3/view/api.mjs +1 -1
- package/esm2022/src/render3/view/compiler.mjs +24 -8
- package/esm2022/src/render3/view/t2_api.mjs +1 -1
- package/esm2022/src/render3/view/t2_binder.mjs +47 -13
- package/esm2022/src/render3/view/template.mjs +41 -5
- package/esm2022/src/template/pipeline/ir/index.mjs +2 -1
- package/esm2022/src/template/pipeline/ir/src/element.mjs +23 -19
- package/esm2022/src/template/pipeline/ir/src/enums.mjs +59 -30
- package/esm2022/src/template/pipeline/ir/src/expression.mjs +50 -21
- package/esm2022/src/template/pipeline/ir/src/operations.mjs +26 -10
- package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +64 -5
- package/esm2022/src/template/pipeline/ir/src/ops/host.mjs +21 -0
- package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +50 -88
- package/esm2022/src/template/pipeline/ir/src/traits.mjs +1 -1
- package/esm2022/src/template/pipeline/src/compilation.mjs +87 -48
- package/esm2022/src/template/pipeline/src/conversion.mjs +23 -1
- package/esm2022/src/template/pipeline/src/emit.mjs +105 -30
- package/esm2022/src/template/pipeline/src/ingest.mjs +92 -104
- package/esm2022/src/template/pipeline/src/instruction.mjs +86 -55
- package/esm2022/src/template/pipeline/src/phases/align_pipe_variadic_var_offset.mjs +1 -1
- package/esm2022/src/template/pipeline/src/phases/any_cast.mjs +30 -0
- package/esm2022/src/template/pipeline/src/phases/attribute_extraction.mjs +60 -49
- package/esm2022/src/template/pipeline/src/phases/binding_specialization.mjs +64 -0
- package/esm2022/src/template/pipeline/src/phases/chaining.mjs +9 -5
- package/esm2022/src/template/pipeline/src/phases/const_collection.mjs +1 -1
- package/esm2022/src/template/pipeline/src/phases/empty_elements.mjs +1 -1
- package/esm2022/src/template/pipeline/src/phases/expand_safe_reads.mjs +18 -12
- package/esm2022/src/template/pipeline/src/phases/generate_advance.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/generate_variables.mjs +6 -6
- package/esm2022/src/template/pipeline/src/phases/host_style_property_parsing.mjs +64 -0
- package/esm2022/src/template/pipeline/src/phases/local_refs.mjs +1 -1
- package/esm2022/src/template/pipeline/src/phases/namespace.mjs +26 -0
- package/esm2022/src/template/pipeline/src/phases/naming.mjs +32 -15
- package/esm2022/src/template/pipeline/src/phases/next_context_merging.mjs +1 -1
- package/esm2022/src/template/pipeline/src/phases/ng_container.mjs +1 -1
- package/esm2022/src/template/pipeline/src/phases/no_listeners_on_templates.mjs +36 -0
- package/esm2022/src/template/pipeline/src/phases/nonbindable.mjs +47 -0
- package/esm2022/src/template/pipeline/src/phases/nullish_coalescing.mjs +5 -5
- package/esm2022/src/template/pipeline/src/phases/pipe_creation.mjs +1 -1
- package/esm2022/src/template/pipeline/src/phases/pipe_variadic.mjs +1 -1
- package/esm2022/src/template/pipeline/src/phases/property_ordering.mjs +30 -13
- package/esm2022/src/template/pipeline/src/phases/pure_function_extraction.mjs +4 -4
- package/esm2022/src/template/pipeline/src/phases/pure_literal_structures.mjs +3 -3
- package/esm2022/src/template/pipeline/src/phases/reify.mjs +94 -57
- package/esm2022/src/template/pipeline/src/phases/remove_empty_bindings.mjs +28 -0
- package/esm2022/src/template/pipeline/src/phases/resolve_contexts.mjs +4 -4
- package/esm2022/src/template/pipeline/src/phases/resolve_dollar_event.mjs +33 -0
- package/esm2022/src/template/pipeline/src/phases/resolve_names.mjs +13 -9
- package/esm2022/src/template/pipeline/src/phases/resolve_sanitizers.mjs +58 -0
- package/esm2022/src/template/pipeline/src/phases/save_restore_view.mjs +3 -3
- package/esm2022/src/template/pipeline/src/phases/slot_allocation.mjs +1 -1
- package/esm2022/src/template/pipeline/src/phases/style_binding_specialization.mjs +42 -0
- package/esm2022/src/template/pipeline/src/phases/temporary_variables.mjs +40 -20
- package/esm2022/src/template/pipeline/src/phases/var_counting.mjs +33 -30
- package/esm2022/src/template/pipeline/src/phases/variable_optimization.mjs +10 -9
- package/esm2022/src/template/pipeline/src/util/elements.mjs +22 -0
- package/esm2022/src/version.mjs +1 -1
- package/fesm2022/compiler.mjs +1805 -975
- package/fesm2022/compiler.mjs.map +1 -1
- package/fesm2022/testing.mjs +1 -1
- package/index.d.ts +60 -5
- package/package.json +2 -2
- package/testing/index.d.ts +1 -1
package/fesm2022/compiler.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v16.2.0-
|
|
2
|
+
* @license Angular v16.2.0-rc.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
|
|
8656
|
-
(function (
|
|
8656
|
+
var BindingKind;
|
|
8657
|
+
(function (BindingKind) {
|
|
8657
8658
|
/**
|
|
8658
8659
|
* Static attributes.
|
|
8659
8660
|
*/
|
|
8660
|
-
|
|
8661
|
+
BindingKind[BindingKind["Attribute"] = 0] = "Attribute";
|
|
8661
8662
|
/**
|
|
8662
8663
|
* Class bindings.
|
|
8663
8664
|
*/
|
|
8664
|
-
|
|
8665
|
+
BindingKind[BindingKind["ClassName"] = 1] = "ClassName";
|
|
8665
8666
|
/**
|
|
8666
8667
|
* Style bindings.
|
|
8667
8668
|
*/
|
|
8668
|
-
|
|
8669
|
+
BindingKind[BindingKind["StyleProperty"] = 2] = "StyleProperty";
|
|
8669
8670
|
/**
|
|
8670
|
-
* Dynamic property
|
|
8671
|
+
* Dynamic property bindings.
|
|
8671
8672
|
*/
|
|
8672
|
-
|
|
8673
|
+
BindingKind[BindingKind["Property"] = 3] = "Property";
|
|
8673
8674
|
/**
|
|
8674
|
-
*
|
|
8675
|
+
* Property or attribute bindings on a template.
|
|
8675
8676
|
*/
|
|
8676
|
-
|
|
8677
|
+
BindingKind[BindingKind["Template"] = 4] = "Template";
|
|
8677
8678
|
/**
|
|
8678
8679
|
* Internationalized attributes.
|
|
8679
8680
|
*/
|
|
8680
|
-
|
|
8681
|
-
|
|
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(
|
|
8698
|
+
return this.byKind.get(BindingKind.Attribute) ?? FLYWEIGHT_ARRAY;
|
|
8694
8699
|
}
|
|
8695
8700
|
get classes() {
|
|
8696
|
-
return this.byKind.get(
|
|
8701
|
+
return this.byKind.get(BindingKind.ClassName) ?? FLYWEIGHT_ARRAY;
|
|
8697
8702
|
}
|
|
8698
8703
|
get styles() {
|
|
8699
|
-
return this.byKind.get(
|
|
8704
|
+
return this.byKind.get(BindingKind.StyleProperty) ?? FLYWEIGHT_ARRAY;
|
|
8700
8705
|
}
|
|
8701
8706
|
get bindings() {
|
|
8702
|
-
return this.byKind.get(
|
|
8707
|
+
return this.byKind.get(BindingKind.Property) ?? FLYWEIGHT_ARRAY;
|
|
8703
8708
|
}
|
|
8704
8709
|
get template() {
|
|
8705
|
-
return this.byKind.get(
|
|
8710
|
+
return this.byKind.get(BindingKind.Template) ?? FLYWEIGHT_ARRAY;
|
|
8706
8711
|
}
|
|
8707
8712
|
get i18n() {
|
|
8708
|
-
return this.byKind.get(
|
|
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 ===
|
|
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"] =
|
|
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"] =
|
|
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"] =
|
|
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"] =
|
|
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"] =
|
|
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"] =
|
|
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"] =
|
|
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"] =
|
|
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"] =
|
|
8849
|
+
OpKind[OpKind["Advance"] = 21] = "Advance";
|
|
8847
8850
|
/**
|
|
8848
8851
|
* An operation to instantiate a pipe.
|
|
8849
8852
|
*/
|
|
8850
|
-
OpKind[OpKind["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"] =
|
|
8857
|
+
OpKind[OpKind["Attribute"] = 23] = "Attribute";
|
|
8855
8858
|
/**
|
|
8856
|
-
*
|
|
8859
|
+
* A host binding property.
|
|
8857
8860
|
*/
|
|
8858
|
-
OpKind[OpKind["
|
|
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
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
|
|
9604
|
-
|
|
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.
|
|
9610
|
-
transformExpressionsInStatement(op.statement, transform, flags);
|
|
9611
|
-
break;
|
|
9839
|
+
case OpKind.Property:
|
|
9612
9840
|
case OpKind.Attribute:
|
|
9613
|
-
if (op.
|
|
9614
|
-
|
|
9841
|
+
if (op.expression instanceof Interpolation) {
|
|
9842
|
+
transformExpressionsInInterpolation(op.expression, transform, flags);
|
|
9615
9843
|
}
|
|
9616
|
-
|
|
9617
|
-
|
|
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 `
|
|
10147
|
+
* Insert `op` before `target`.
|
|
9911
10148
|
*/
|
|
9912
|
-
static insertBefore(op,
|
|
9913
|
-
OpList.assertIsOwned(
|
|
9914
|
-
if (
|
|
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 =
|
|
10156
|
+
op.debugListId = target.debugListId;
|
|
9920
10157
|
// Just in case.
|
|
9921
10158
|
op.prev = null;
|
|
9922
|
-
|
|
9923
|
-
op.prev =
|
|
9924
|
-
op.next =
|
|
9925
|
-
|
|
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
|
|
10315
|
+
* Create a `ListenerOp` for an animation.
|
|
10082
10316
|
*/
|
|
10083
|
-
function
|
|
10317
|
+
function createListenerOpForAnimation(target, name, animationPhase, tag) {
|
|
10084
10318
|
return {
|
|
10085
|
-
kind: OpKind.
|
|
10086
|
-
target
|
|
10087
|
-
|
|
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
|
-
|
|
10131
|
-
|
|
10132
|
-
|
|
10133
|
-
|
|
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.
|
|
10166
|
-
|
|
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
|
-
*
|
|
10342
|
+
* Whether the active namespace is HTML, MathML, or SVG mode.
|
|
10177
10343
|
*/
|
|
10178
|
-
|
|
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.
|
|
10181
|
-
|
|
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
|
-
|
|
10357
|
+
|
|
10358
|
+
function createHostPropertyOp(name, expression, sourceSpan) {
|
|
10192
10359
|
return {
|
|
10193
|
-
kind: OpKind.
|
|
10194
|
-
target: target,
|
|
10195
|
-
attributeKind,
|
|
10360
|
+
kind: OpKind.HostProperty,
|
|
10196
10361
|
name,
|
|
10197
|
-
|
|
10198
|
-
|
|
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
|
-
*
|
|
10370
|
+
* A compilation unit is compiled into a template function.
|
|
10371
|
+
* Some example units are views and host bindings.
|
|
10206
10372
|
*/
|
|
10207
|
-
|
|
10208
|
-
|
|
10209
|
-
|
|
10210
|
-
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
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
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
|
|
10225
|
-
|
|
10226
|
-
|
|
10227
|
-
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10241
|
-
|
|
10242
|
-
|
|
10243
|
-
|
|
10244
|
-
|
|
10245
|
-
|
|
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
|
-
*
|
|
10500
|
+
* Compilation-in-progress of an individual view within a template.
|
|
10250
10501
|
*/
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
|
|
10254
|
-
|
|
10255
|
-
|
|
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(
|
|
10527
|
+
function phaseVarCounting(job) {
|
|
10264
10528
|
// First, count the vars used in each view, and update the view-level counter.
|
|
10265
|
-
for (const
|
|
10529
|
+
for (const unit of job.units) {
|
|
10266
10530
|
let varCount = 0;
|
|
10267
|
-
for (const op of
|
|
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
|
-
|
|
10548
|
+
unit.vars = varCount;
|
|
10285
10549
|
}
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
for (const
|
|
10290
|
-
|
|
10291
|
-
|
|
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
|
-
//
|
|
10307
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
10647
|
+
function phaseFindAnyCasts(cpl) {
|
|
10383
10648
|
for (const [_, view] of cpl.views) {
|
|
10384
|
-
|
|
10649
|
+
for (const op of view.ops()) {
|
|
10650
|
+
transformExpressionsInOp(op, removeAnys, VisitorContextFlag.None);
|
|
10651
|
+
}
|
|
10385
10652
|
}
|
|
10386
10653
|
}
|
|
10387
|
-
|
|
10388
|
-
|
|
10389
|
-
|
|
10390
|
-
|
|
10391
|
-
|
|
10392
|
-
|
|
10393
|
-
|
|
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
|
|
10662
|
+
return e;
|
|
10396
10663
|
}
|
|
10664
|
+
|
|
10397
10665
|
/**
|
|
10398
|
-
*
|
|
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
|
|
10401
|
-
|
|
10402
|
-
|
|
10403
|
-
|
|
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
|
+
}
|
|
10729
|
+
}
|
|
10730
|
+
if (currentProp && valueStart) {
|
|
10731
|
+
const styleVal = value.slice(valueStart).trim();
|
|
10732
|
+
styles.push(currentProp, styleVal);
|
|
10404
10733
|
}
|
|
10405
|
-
return
|
|
10734
|
+
return styles;
|
|
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();
|
|
10406
10742
|
}
|
|
10743
|
+
|
|
10407
10744
|
/**
|
|
10408
|
-
*
|
|
10409
|
-
* not need further processing.
|
|
10745
|
+
* Gets a map of all elements in the given view by their xref id.
|
|
10410
10746
|
*/
|
|
10411
|
-
function
|
|
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
|
-
|
|
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
|
-
|
|
10438
|
-
|
|
10439
|
-
|
|
10440
|
-
ownerOp
|
|
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.
|
|
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
|
-
//
|
|
10452
|
-
//
|
|
10453
|
-
if (
|
|
10454
|
-
|
|
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
|
-
|
|
10459
|
-
|
|
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(
|
|
10508
|
-
for (const
|
|
10509
|
-
chainOperationsInList(
|
|
10510
|
-
chainOperationsInList(
|
|
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(
|
|
10632
|
-
for (const
|
|
10633
|
-
for (const op of
|
|
10634
|
-
transformExpressionsInOp(op, e => safeTransform(e, {
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
10952
|
-
newOps.push(createVariableOp(view.
|
|
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.
|
|
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,111 +11415,39 @@ function generateVariablesInScopeForView(view, scope) {
|
|
|
10962
11415
|
return newOps;
|
|
10963
11416
|
}
|
|
10964
11417
|
|
|
10965
|
-
|
|
10966
|
-
|
|
10967
|
-
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
|
|
10972
|
-
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
|
|
10977
|
-
throw new Error(`AssertionError: expected localRefs to be an array still`);
|
|
10978
|
-
}
|
|
10979
|
-
op.numSlotsUsed += op.localRefs.length;
|
|
10980
|
-
if (op.localRefs.length > 0) {
|
|
10981
|
-
const localRefs = serializeLocalRefs(op.localRefs);
|
|
10982
|
-
op.localRefs = cpl.addConst(localRefs);
|
|
10983
|
-
}
|
|
10984
|
-
else {
|
|
10985
|
-
op.localRefs = null;
|
|
10986
|
-
}
|
|
10987
|
-
break;
|
|
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);
|
|
10988
11430
|
}
|
|
11431
|
+
const { property, suffix } = parseProperty$1(op.name);
|
|
11432
|
+
op.name = property;
|
|
11433
|
+
op.unit = suffix;
|
|
10989
11434
|
}
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
10996
|
-
|
|
10997
|
-
return literalArr(constRefs);
|
|
10998
|
-
}
|
|
10999
|
-
|
|
11000
|
-
/**
|
|
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']`
|
|
11007
|
-
*/
|
|
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;
|
|
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;
|
|
11063
11442
|
}
|
|
11064
11443
|
}
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
|
|
11069
|
-
|
|
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('--');
|
|
11070
11451
|
}
|
|
11071
11452
|
function hyphenate(value) {
|
|
11072
11453
|
return value
|
|
@@ -11075,6 +11456,114 @@ function hyphenate(value) {
|
|
|
11075
11456
|
})
|
|
11076
11457
|
.toLowerCase();
|
|
11077
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
|
+
|
|
11474
|
+
/**
|
|
11475
|
+
* Lifts local reference declarations on element-like structures within each view into an entry in
|
|
11476
|
+
* the `consts` array for the whole component.
|
|
11477
|
+
*/
|
|
11478
|
+
function phaseLocalRefs(cpl) {
|
|
11479
|
+
for (const view of cpl.views.values()) {
|
|
11480
|
+
for (const op of view.create) {
|
|
11481
|
+
switch (op.kind) {
|
|
11482
|
+
case OpKind.ElementStart:
|
|
11483
|
+
case OpKind.Element:
|
|
11484
|
+
case OpKind.Template:
|
|
11485
|
+
if (!Array.isArray(op.localRefs)) {
|
|
11486
|
+
throw new Error(`AssertionError: expected localRefs to be an array still`);
|
|
11487
|
+
}
|
|
11488
|
+
op.numSlotsUsed += op.localRefs.length;
|
|
11489
|
+
if (op.localRefs.length > 0) {
|
|
11490
|
+
const localRefs = serializeLocalRefs(op.localRefs);
|
|
11491
|
+
op.localRefs = cpl.addConst(localRefs);
|
|
11492
|
+
}
|
|
11493
|
+
else {
|
|
11494
|
+
op.localRefs = null;
|
|
11495
|
+
}
|
|
11496
|
+
break;
|
|
11497
|
+
}
|
|
11498
|
+
}
|
|
11499
|
+
}
|
|
11500
|
+
}
|
|
11501
|
+
function serializeLocalRefs(refs) {
|
|
11502
|
+
const constRefs = [];
|
|
11503
|
+
for (const ref of refs) {
|
|
11504
|
+
constRefs.push(literal(ref.name), literal(ref.target));
|
|
11505
|
+
}
|
|
11506
|
+
return literalArr(constRefs);
|
|
11507
|
+
}
|
|
11508
|
+
|
|
11509
|
+
/**
|
|
11510
|
+
* Change namespaces between HTML, SVG and MathML, depending on the next element.
|
|
11511
|
+
*/
|
|
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
|
+
}
|
|
11523
|
+
}
|
|
11524
|
+
}
|
|
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;
|
|
11550
|
+
}
|
|
11551
|
+
return NAMESPACES.get(namespacePrefixKey) ?? Namespace.HTML;
|
|
11552
|
+
}
|
|
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}`;
|
|
11566
|
+
}
|
|
11078
11567
|
|
|
11079
11568
|
/**
|
|
11080
11569
|
* Generate names for functions and variables across all views.
|
|
@@ -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
|
|
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(
|
|
11089
|
-
if (
|
|
11090
|
-
|
|
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
|
|
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.
|
|
11105
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
11261
|
-
|
|
11262
|
-
|
|
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(),
|
|
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
|
-
{
|
|
11350
|
-
{
|
|
11351
|
-
{
|
|
11352
|
-
{
|
|
11353
|
-
{
|
|
11354
|
-
|
|
11355
|
-
|
|
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(
|
|
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
|
|
11960
|
+
for (const unit of cpl.units) {
|
|
11373
11961
|
let opsToOrder = [];
|
|
11374
|
-
for (const op of
|
|
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
|
-
|
|
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.
|
|
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(
|
|
11419
|
-
for (const view of
|
|
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 =
|
|
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(
|
|
11463
|
-
for (const view of
|
|
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);
|
|
12167
|
+
}
|
|
12168
|
+
function namespaceMath() {
|
|
12169
|
+
return call(Identifiers.namespaceMathML, [], null);
|
|
11567
12170
|
}
|
|
11568
|
-
function advance(delta) {
|
|
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
|
-
|
|
11603
|
-
|
|
11604
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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])
|
|
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)
|
|
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)
|
|
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
|
|
11907
|
-
reifyCreateOperations(
|
|
11908
|
-
reifyUpdateOperations(
|
|
12535
|
+
for (const unit of cpl.units) {
|
|
12536
|
+
reifyCreateOperations(unit, unit.create);
|
|
12537
|
+
reifyUpdateOperations(unit, unit.update);
|
|
11909
12538
|
}
|
|
11910
12539
|
}
|
|
11911
|
-
function reifyCreateOperations(
|
|
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
|
-
|
|
11938
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
|
|
11985
|
-
|
|
11986
|
-
|
|
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
|
-
|
|
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.
|
|
12002
|
-
|
|
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(
|
|
12073
|
-
const lookForEvent = new LookForEventVisitor();
|
|
12743
|
+
function reifyListenerHandler(unit, name, handlerOps, consumesDollarEvent) {
|
|
12074
12744
|
// First, reify all instruction calls within `handlerOps`.
|
|
12075
|
-
reifyUpdateOperations(
|
|
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
|
-
//
|
|
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 (
|
|
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
|
-
|
|
12097
|
-
|
|
12098
|
-
|
|
12099
|
-
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
|
|
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
|
|
12117
|
-
processLexicalScope$1(
|
|
12118
|
-
processLexicalScope$1(
|
|
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
|
|
12165
|
-
processLexicalScope(
|
|
12166
|
-
processLexicalScope(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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 ${
|
|
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.
|
|
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.
|
|
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
|
|
13169
|
+
for (const unit of cpl.units) {
|
|
12387
13170
|
let opCount = 0;
|
|
12388
13171
|
let generatedStatements = [];
|
|
12389
|
-
for (const op of
|
|
12390
|
-
|
|
12391
|
-
|
|
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
|
|
12395
|
-
|
|
13176
|
+
if (expr instanceof ReadTemporaryExpr) {
|
|
13177
|
+
finalReads.set(expr.xref, expr);
|
|
12396
13178
|
}
|
|
12397
13179
|
});
|
|
12398
|
-
for
|
|
12399
|
-
|
|
12400
|
-
|
|
12401
|
-
|
|
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
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
|
|
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
|
|
13201
|
+
assignName(defs, expr);
|
|
12410
13202
|
}
|
|
12411
13203
|
});
|
|
12412
|
-
|
|
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
|
-
|
|
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(
|
|
12439
|
-
for (const
|
|
12440
|
-
optimizeVariablesInOpList(
|
|
12441
|
-
optimizeVariablesInOpList(
|
|
12442
|
-
for (const op of
|
|
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,
|
|
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,
|
|
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 (
|
|
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
|
|
12786
|
-
*/
|
|
12787
|
-
function transformTemplate(
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12792
|
-
|
|
12793
|
-
|
|
12794
|
-
|
|
12795
|
-
|
|
12796
|
-
|
|
12797
|
-
|
|
12798
|
-
|
|
12799
|
-
|
|
12800
|
-
|
|
12801
|
-
|
|
12802
|
-
|
|
12803
|
-
|
|
12804
|
-
|
|
12805
|
-
|
|
12806
|
-
|
|
12807
|
-
|
|
12808
|
-
|
|
12809
|
-
|
|
12810
|
-
|
|
12811
|
-
|
|
12812
|
-
|
|
12813
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
12920
|
-
|
|
12921
|
-
|
|
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
|
-
|
|
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
|
-
|
|
12974
|
-
|
|
12975
|
-
|
|
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
|
|
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
|
|
13017
|
-
const cpl = new
|
|
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.
|
|
13052
|
-
const
|
|
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.
|
|
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,
|
|
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.
|
|
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.
|
|
13092
|
-
view.create.push(createTextOp(textXref, ''));
|
|
13093
|
-
view.update.push(createInterpolateTextOp(textXref, value.strings, value.expressions.map(expr => convertAst(expr, view.
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
13239
|
-
|
|
13240
|
-
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
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
|
-
|
|
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
|
/**
|
|
@@ -18510,10 +19231,10 @@ class _Tokenizer {
|
|
|
18510
19231
|
this._beginToken(28 /* TokenType.BLOCK_PARAMETER */);
|
|
18511
19232
|
const start = this._cursor.clone();
|
|
18512
19233
|
let inQuote = null;
|
|
19234
|
+
let openBraces = 0;
|
|
18513
19235
|
// Consume the parameter until the next semicolon or brace.
|
|
18514
19236
|
// Note that we skip over semicolons/braces inside of strings.
|
|
18515
|
-
while ((this._cursor.peek() !== $SEMICOLON && this._cursor.peek() !== $
|
|
18516
|
-
this._cursor.peek() !== $EOF) ||
|
|
19237
|
+
while ((this._cursor.peek() !== $SEMICOLON && this._cursor.peek() !== $EOF) ||
|
|
18517
19238
|
inQuote !== null) {
|
|
18518
19239
|
const char = this._cursor.peek();
|
|
18519
19240
|
// Skip to the next character if it was escaped.
|
|
@@ -18526,6 +19247,17 @@ class _Tokenizer {
|
|
|
18526
19247
|
else if (inQuote === null && isQuote(char)) {
|
|
18527
19248
|
inQuote = char;
|
|
18528
19249
|
}
|
|
19250
|
+
else if (char === $LBRACE && inQuote === null) {
|
|
19251
|
+
openBraces++;
|
|
19252
|
+
}
|
|
19253
|
+
else if (char === $RBRACE && inQuote === null) {
|
|
19254
|
+
if (openBraces === 0) {
|
|
19255
|
+
break;
|
|
19256
|
+
}
|
|
19257
|
+
else if (openBraces > 0) {
|
|
19258
|
+
openBraces--;
|
|
19259
|
+
}
|
|
19260
|
+
}
|
|
18529
19261
|
this._cursor.advance();
|
|
18530
19262
|
}
|
|
18531
19263
|
this._endToken([this._cursor.getChars(start)]);
|
|
@@ -19521,9 +20253,12 @@ class _TreeBuilder {
|
|
|
19521
20253
|
}
|
|
19522
20254
|
_consumeComment(token) {
|
|
19523
20255
|
const text = this._advanceIf(7 /* TokenType.RAW_TEXT */);
|
|
19524
|
-
this._advanceIf(11 /* TokenType.COMMENT_END */);
|
|
20256
|
+
const endToken = this._advanceIf(11 /* TokenType.COMMENT_END */);
|
|
19525
20257
|
const value = text != null ? text.parts[0].trim() : null;
|
|
19526
|
-
|
|
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));
|
|
19527
20262
|
}
|
|
19528
20263
|
_consumeExpansion(token) {
|
|
19529
20264
|
const switchValue = this._advance();
|
|
@@ -22514,7 +23249,7 @@ function createComponentDefConsts() {
|
|
|
22514
23249
|
};
|
|
22515
23250
|
}
|
|
22516
23251
|
class TemplateDefinitionBuilder {
|
|
22517
|
-
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()) {
|
|
22518
23253
|
this.constantPool = constantPool;
|
|
22519
23254
|
this.level = level;
|
|
22520
23255
|
this.contextName = contextName;
|
|
@@ -22523,6 +23258,7 @@ class TemplateDefinitionBuilder {
|
|
|
22523
23258
|
this.templateName = templateName;
|
|
22524
23259
|
this._namespace = _namespace;
|
|
22525
23260
|
this.i18nUseExternalIds = i18nUseExternalIds;
|
|
23261
|
+
this.deferBlocks = deferBlocks;
|
|
22526
23262
|
this._constants = _constants;
|
|
22527
23263
|
this._dataIndex = 0;
|
|
22528
23264
|
this._bindingContext = 0;
|
|
@@ -22725,7 +23461,7 @@ class TemplateDefinitionBuilder {
|
|
|
22725
23461
|
else {
|
|
22726
23462
|
const value = prop.value.visit(this._valueConverter);
|
|
22727
23463
|
this.allocateBindingSlots(value);
|
|
22728
|
-
if (value instanceof Interpolation) {
|
|
23464
|
+
if (value instanceof Interpolation$1) {
|
|
22729
23465
|
const { strings, expressions } = value;
|
|
22730
23466
|
const { id, bindings } = this.i18n;
|
|
22731
23467
|
const label = assembleI18nBoundString(strings, bindings.size, id);
|
|
@@ -22845,7 +23581,7 @@ class TemplateDefinitionBuilder {
|
|
|
22845
23581
|
const message = attr.i18n;
|
|
22846
23582
|
const converted = attr.value.visit(this._valueConverter);
|
|
22847
23583
|
this.allocateBindingSlots(converted);
|
|
22848
|
-
if (converted instanceof Interpolation) {
|
|
23584
|
+
if (converted instanceof Interpolation$1) {
|
|
22849
23585
|
const placeholders = assembleBoundTextPlaceholders(message);
|
|
22850
23586
|
const params = placeholdersToParams(placeholders);
|
|
22851
23587
|
i18nAttrArgs.push(literal(attr.name), this.i18nTranslate(message, params));
|
|
@@ -23065,7 +23801,7 @@ class TemplateDefinitionBuilder {
|
|
|
23065
23801
|
}
|
|
23066
23802
|
this.allocateBindingSlots(value);
|
|
23067
23803
|
if (inputType === 0 /* BindingType.Property */) {
|
|
23068
|
-
if (value instanceof Interpolation) {
|
|
23804
|
+
if (value instanceof Interpolation$1) {
|
|
23069
23805
|
// prop="{{value}}" and friends
|
|
23070
23806
|
this.interpolatedUpdateInstruction(getPropertyInterpolationExpression(value), elementIndex, attrName, input, value, params);
|
|
23071
23807
|
}
|
|
@@ -23079,12 +23815,12 @@ class TemplateDefinitionBuilder {
|
|
|
23079
23815
|
}
|
|
23080
23816
|
}
|
|
23081
23817
|
else if (inputType === 1 /* BindingType.Attribute */) {
|
|
23082
|
-
if (value instanceof Interpolation && getInterpolationArgsLength(value) > 1) {
|
|
23818
|
+
if (value instanceof Interpolation$1 && getInterpolationArgsLength(value) > 1) {
|
|
23083
23819
|
// attr.name="text{{value}}" and friends
|
|
23084
23820
|
this.interpolatedUpdateInstruction(getAttributeInterpolationExpression(value), elementIndex, attrName, input, value, params);
|
|
23085
23821
|
}
|
|
23086
23822
|
else {
|
|
23087
|
-
const boundValue = value instanceof Interpolation ? value.expressions[0] : value;
|
|
23823
|
+
const boundValue = value instanceof Interpolation$1 ? value.expressions[0] : value;
|
|
23088
23824
|
// [attr.name]="value" or attr.name="{{value}}"
|
|
23089
23825
|
// Collect the attribute bindings so that they can be chained at the end.
|
|
23090
23826
|
attributeBindings.push({
|
|
@@ -23154,7 +23890,7 @@ class TemplateDefinitionBuilder {
|
|
|
23154
23890
|
parameters.push(importExpr(Identifiers.templateRefExtractor));
|
|
23155
23891
|
}
|
|
23156
23892
|
// Create the template function
|
|
23157
|
-
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);
|
|
23158
23894
|
// Nested templates must not be visited until after their parent templates have completed
|
|
23159
23895
|
// processing, so they are queued here until after the initial pass. Otherwise, we wouldn't
|
|
23160
23896
|
// be able to support bindings in nested templates to local refs that occur after the
|
|
@@ -23197,7 +23933,7 @@ class TemplateDefinitionBuilder {
|
|
|
23197
23933
|
if (this.i18n) {
|
|
23198
23934
|
const value = text.value.visit(this._valueConverter);
|
|
23199
23935
|
this.allocateBindingSlots(value);
|
|
23200
|
-
if (value instanceof Interpolation) {
|
|
23936
|
+
if (value instanceof Interpolation$1) {
|
|
23201
23937
|
this.i18n.appendBoundText(text.i18n);
|
|
23202
23938
|
this.i18nAppendBindings(value.expressions);
|
|
23203
23939
|
}
|
|
@@ -23207,7 +23943,7 @@ class TemplateDefinitionBuilder {
|
|
|
23207
23943
|
this.creationInstruction(text.sourceSpan, Identifiers.text, [literal(nodeIndex)]);
|
|
23208
23944
|
const value = text.value.visit(this._valueConverter);
|
|
23209
23945
|
this.allocateBindingSlots(value);
|
|
23210
|
-
if (value instanceof Interpolation) {
|
|
23946
|
+
if (value instanceof Interpolation$1) {
|
|
23211
23947
|
this.updateInstructionWithAdvance(nodeIndex, text.sourceSpan, getTextInterpolationExpression(value), () => this.getUpdateInstructionArguments(value));
|
|
23212
23948
|
}
|
|
23213
23949
|
else {
|
|
@@ -23264,8 +24000,43 @@ class TemplateDefinitionBuilder {
|
|
|
23264
24000
|
}
|
|
23265
24001
|
return null;
|
|
23266
24002
|
}
|
|
23267
|
-
|
|
23268
|
-
|
|
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.
|
|
23269
24040
|
visitDeferredTrigger(trigger) { }
|
|
23270
24041
|
visitDeferredBlockPlaceholder(block) { }
|
|
23271
24042
|
visitDeferredBlockError(block) { }
|
|
@@ -23301,7 +24072,7 @@ class TemplateDefinitionBuilder {
|
|
|
23301
24072
|
continue;
|
|
23302
24073
|
}
|
|
23303
24074
|
this.allocateBindingSlots(value);
|
|
23304
|
-
if (value instanceof Interpolation) {
|
|
24075
|
+
if (value instanceof Interpolation$1) {
|
|
23305
24076
|
// Params typically contain attribute namespace and value sanitizer, which is applicable
|
|
23306
24077
|
// for regular HTML elements, but not applicable for <ng-template> (since props act as
|
|
23307
24078
|
// inputs to directives), so keep params array empty.
|
|
@@ -23333,7 +24104,7 @@ class TemplateDefinitionBuilder {
|
|
|
23333
24104
|
if (instruction) {
|
|
23334
24105
|
for (const call of instruction.calls) {
|
|
23335
24106
|
allocateBindingSlots += call.allocateBindingSlots;
|
|
23336
|
-
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) ?
|
|
23337
24108
|
this.getUpdateInstructionArguments(value) :
|
|
23338
24109
|
this.convertPropertyBinding(value)));
|
|
23339
24110
|
}
|
|
@@ -23366,7 +24137,7 @@ class TemplateDefinitionBuilder {
|
|
|
23366
24137
|
return originalSlots;
|
|
23367
24138
|
}
|
|
23368
24139
|
allocateBindingSlots(value) {
|
|
23369
|
-
this._bindingSlots += value instanceof Interpolation ? value.expressions.length : 1;
|
|
24140
|
+
this._bindingSlots += value instanceof Interpolation$1 ? value.expressions.length : 1;
|
|
23370
24141
|
}
|
|
23371
24142
|
/**
|
|
23372
24143
|
* Gets an expression that refers to the implicit receiver. The implicit
|
|
@@ -24319,7 +25090,7 @@ function compileComponentFromMetadata(meta, constantPool, bindingParser) {
|
|
|
24319
25090
|
// This is the main path currently used in compilation, which compiles the template with the
|
|
24320
25091
|
// legacy `TemplateDefinitionBuilder`.
|
|
24321
25092
|
const template = meta.template;
|
|
24322
|
-
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);
|
|
24323
25094
|
const templateFunctionExpression = templateBuilder.buildTemplateFunction(template.nodes, []);
|
|
24324
25095
|
// We need to provide this so that dynamically generated components know what
|
|
24325
25096
|
// projected content blocks to pass through to the component when it is
|
|
@@ -24354,7 +25125,7 @@ function compileComponentFromMetadata(meta, constantPool, bindingParser) {
|
|
|
24354
25125
|
else {
|
|
24355
25126
|
// This path compiles the template using the prototype template pipeline. First the template is
|
|
24356
25127
|
// ingested into IR:
|
|
24357
|
-
const tpl =
|
|
25128
|
+
const tpl = ingestComponent(meta.name, meta.template.nodes, constantPool);
|
|
24358
25129
|
// Then the IR is transformed to prepare it for cod egeneration.
|
|
24359
25130
|
transformTemplate(tpl);
|
|
24360
25131
|
// Finally we emit the template function:
|
|
@@ -24583,6 +25354,25 @@ function createViewQueriesFunction(viewQueries, constantPool, name) {
|
|
|
24583
25354
|
}
|
|
24584
25355
|
// Return a host binding function or null if one is not necessary.
|
|
24585
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
|
+
}
|
|
24586
25376
|
const bindingContext = variable(CONTEXT_NAME);
|
|
24587
25377
|
const styleBuilder = new StylingBuilder(bindingContext);
|
|
24588
25378
|
const { styleAttr, classAttr } = hostBindingsMetadata.specialAttributes;
|
|
@@ -24596,13 +25386,10 @@ function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindin
|
|
|
24596
25386
|
const updateInstructions = [];
|
|
24597
25387
|
const updateVariables = [];
|
|
24598
25388
|
const hostBindingSourceSpan = typeSourceSpan;
|
|
24599
|
-
// Calculate host event bindings
|
|
24600
|
-
const eventBindings = bindingParser.createDirectiveHostEventAsts(hostBindingsMetadata.listeners, hostBindingSourceSpan);
|
|
24601
25389
|
if (eventBindings && eventBindings.length) {
|
|
24602
25390
|
createInstructions.push(...createHostListeners(eventBindings, name));
|
|
24603
25391
|
}
|
|
24604
25392
|
// Calculate the host property bindings
|
|
24605
|
-
const bindings = bindingParser.createBoundHostProperties(hostBindingsMetadata.properties, hostBindingSourceSpan);
|
|
24606
25393
|
const allOtherBindings = [];
|
|
24607
25394
|
// We need to calculate the total amount of binding slots required by
|
|
24608
25395
|
// all the instructions together before any value conversions happen.
|
|
@@ -24945,6 +25732,11 @@ function createHostDirectivesMappingArray(mapping) {
|
|
|
24945
25732
|
class ResourceLoader {
|
|
24946
25733
|
}
|
|
24947
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
|
+
}
|
|
24948
25740
|
class CompilerFacadeImpl {
|
|
24949
25741
|
constructor(jitEvaluator = new JitEvaluator()) {
|
|
24950
25742
|
this.jitEvaluator = jitEvaluator;
|
|
@@ -25065,6 +25857,10 @@ class CompilerFacadeImpl {
|
|
|
25065
25857
|
template,
|
|
25066
25858
|
declarations: facade.declarations.map(convertDeclarationFacadeToMetadata),
|
|
25067
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(),
|
|
25068
25864
|
styles: [...facade.styles, ...template.styles],
|
|
25069
25865
|
encapsulation: facade.encapsulation,
|
|
25070
25866
|
interpolation,
|
|
@@ -25295,6 +26091,10 @@ function convertDeclareComponentFacadeToMetadata(decl, typeSourceSpan, sourceMap
|
|
|
25295
26091
|
viewProviders: decl.viewProviders !== undefined ? new WrappedNodeExpr(decl.viewProviders) :
|
|
25296
26092
|
null,
|
|
25297
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(),
|
|
25298
26098
|
changeDetection: decl.changeDetection ?? ChangeDetectionStrategy.Default,
|
|
25299
26099
|
encapsulation: decl.encapsulation ?? ViewEncapsulation.Emulated,
|
|
25300
26100
|
interpolation,
|
|
@@ -25342,11 +26142,7 @@ function convertPipeDeclarationToMetadata(pipe) {
|
|
|
25342
26142
|
function parseJitTemplate(template, typeName, sourceMapUrl, preserveWhitespaces, interpolation) {
|
|
25343
26143
|
const interpolationConfig = interpolation ? InterpolationConfig.fromArray(interpolation) : DEFAULT_INTERPOLATION_CONFIG;
|
|
25344
26144
|
// Parse the template and check for errors.
|
|
25345
|
-
const parsed = parseTemplate(template, sourceMapUrl, {
|
|
25346
|
-
preserveWhitespaces,
|
|
25347
|
-
interpolationConfig,
|
|
25348
|
-
enabledBlockTypes: new Set(), // TODO: enable deferred blocks when testing in JIT mode.
|
|
25349
|
-
});
|
|
26145
|
+
const parsed = parseTemplate(template, sourceMapUrl, { preserveWhitespaces, interpolationConfig, enabledBlockTypes });
|
|
25350
26146
|
if (parsed.errors !== null) {
|
|
25351
26147
|
const errors = parsed.errors.map(err => err.toString()).join(', ');
|
|
25352
26148
|
throw new Error(`Errors during JIT compilation of template for ${typeName}: ${errors}`);
|
|
@@ -25535,7 +26331,7 @@ function publishFacade(global) {
|
|
|
25535
26331
|
* @description
|
|
25536
26332
|
* Entry point for all public APIs of the compiler package.
|
|
25537
26333
|
*/
|
|
25538
|
-
const VERSION = new Version('16.2.0-
|
|
26334
|
+
const VERSION = new Version('16.2.0-rc.0');
|
|
25539
26335
|
|
|
25540
26336
|
class CompilerConfig {
|
|
25541
26337
|
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, useJit = true, missingTranslation = null, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
@@ -27003,11 +27799,11 @@ class R3TargetBinder {
|
|
|
27003
27799
|
// - bindings: Map of inputs, outputs, and attributes to the directive/element that claims
|
|
27004
27800
|
// them. TODO(alxhub): handle multiple directives claiming an input/output/etc.
|
|
27005
27801
|
// - references: Map of #references to their targets.
|
|
27006
|
-
const { directives, bindings, references } = DirectiveBinder.apply(target.template, this.directiveMatcher);
|
|
27802
|
+
const { directives, eagerDirectives, bindings, references } = DirectiveBinder.apply(target.template, this.directiveMatcher);
|
|
27007
27803
|
// Finally, run the TemplateBinder to bind references, variables, and other entities within the
|
|
27008
27804
|
// template. This extracts all the metadata that doesn't depend on directive matching.
|
|
27009
|
-
const { expressions, symbols, nestingLevel, usedPipes } = TemplateBinder.applyWithScope(target.template, scope);
|
|
27010
|
-
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);
|
|
27011
27807
|
}
|
|
27012
27808
|
}
|
|
27013
27809
|
/**
|
|
@@ -27148,11 +27944,14 @@ class Scope {
|
|
|
27148
27944
|
* Usually used via the static `apply()` method.
|
|
27149
27945
|
*/
|
|
27150
27946
|
class DirectiveBinder {
|
|
27151
|
-
constructor(matcher, directives, bindings, references) {
|
|
27947
|
+
constructor(matcher, directives, eagerDirectives, bindings, references) {
|
|
27152
27948
|
this.matcher = matcher;
|
|
27153
27949
|
this.directives = directives;
|
|
27950
|
+
this.eagerDirectives = eagerDirectives;
|
|
27154
27951
|
this.bindings = bindings;
|
|
27155
27952
|
this.references = references;
|
|
27953
|
+
// Indicates whether we are visiting elements within a {#defer} block
|
|
27954
|
+
this.isInDeferBlock = false;
|
|
27156
27955
|
}
|
|
27157
27956
|
/**
|
|
27158
27957
|
* Process a template (list of `Node`s) and perform directive matching against each node.
|
|
@@ -27170,9 +27969,10 @@ class DirectiveBinder {
|
|
|
27170
27969
|
const directives = new Map();
|
|
27171
27970
|
const bindings = new Map();
|
|
27172
27971
|
const references = new Map();
|
|
27173
|
-
const
|
|
27972
|
+
const eagerDirectives = [];
|
|
27973
|
+
const matcher = new DirectiveBinder(selectorMatcher, directives, eagerDirectives, bindings, references);
|
|
27174
27974
|
matcher.ingest(template);
|
|
27175
|
-
return { directives, bindings, references };
|
|
27975
|
+
return { directives, eagerDirectives, bindings, references };
|
|
27176
27976
|
}
|
|
27177
27977
|
ingest(template) {
|
|
27178
27978
|
template.forEach(node => node.visit(this));
|
|
@@ -27192,6 +27992,9 @@ class DirectiveBinder {
|
|
|
27192
27992
|
this.matcher.match(cssSelector, (_selector, results) => directives.push(...results));
|
|
27193
27993
|
if (directives.length > 0) {
|
|
27194
27994
|
this.directives.set(node, directives);
|
|
27995
|
+
if (!this.isInDeferBlock) {
|
|
27996
|
+
this.eagerDirectives.push(...directives);
|
|
27997
|
+
}
|
|
27195
27998
|
}
|
|
27196
27999
|
// Resolve any references that are created on this node.
|
|
27197
28000
|
node.references.forEach(ref => {
|
|
@@ -27242,7 +28045,9 @@ class DirectiveBinder {
|
|
|
27242
28045
|
node.children.forEach(child => child.visit(this));
|
|
27243
28046
|
}
|
|
27244
28047
|
visitDeferredBlock(deferred) {
|
|
28048
|
+
this.isInDeferBlock = true;
|
|
27245
28049
|
deferred.children.forEach(child => child.visit(this));
|
|
28050
|
+
this.isInDeferBlock = false;
|
|
27246
28051
|
deferred.placeholder?.visit(this);
|
|
27247
28052
|
deferred.loading?.visit(this);
|
|
27248
28053
|
deferred.error?.visit(this);
|
|
@@ -27279,15 +28084,19 @@ class DirectiveBinder {
|
|
|
27279
28084
|
* by overridden methods from that visitor.
|
|
27280
28085
|
*/
|
|
27281
28086
|
class TemplateBinder extends RecursiveAstVisitor {
|
|
27282
|
-
constructor(bindings, symbols, usedPipes, nestingLevel, scope, template, level) {
|
|
28087
|
+
constructor(bindings, symbols, usedPipes, eagerPipes, deferBlocks, nestingLevel, scope, template, level) {
|
|
27283
28088
|
super();
|
|
27284
28089
|
this.bindings = bindings;
|
|
27285
28090
|
this.symbols = symbols;
|
|
27286
28091
|
this.usedPipes = usedPipes;
|
|
28092
|
+
this.eagerPipes = eagerPipes;
|
|
28093
|
+
this.deferBlocks = deferBlocks;
|
|
27287
28094
|
this.nestingLevel = nestingLevel;
|
|
27288
28095
|
this.scope = scope;
|
|
27289
28096
|
this.template = template;
|
|
27290
28097
|
this.level = level;
|
|
28098
|
+
// Indicates whether we are visiting elements within a {#defer} block
|
|
28099
|
+
this.isInDeferBlock = false;
|
|
27291
28100
|
// Save a bit of processing time by constructing this closure in advance.
|
|
27292
28101
|
this.visitNode = (node) => node.visit(this);
|
|
27293
28102
|
}
|
|
@@ -27319,11 +28128,13 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
27319
28128
|
const symbols = new Map();
|
|
27320
28129
|
const nestingLevel = new Map();
|
|
27321
28130
|
const usedPipes = new Set();
|
|
28131
|
+
const eagerPipes = new Set();
|
|
27322
28132
|
const template = nodes instanceof Template ? nodes : null;
|
|
28133
|
+
const deferBlocks = new Set();
|
|
27323
28134
|
// The top-level template has nesting level 0.
|
|
27324
|
-
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);
|
|
27325
28136
|
binder.ingest(nodes);
|
|
27326
|
-
return { expressions, symbols, nestingLevel, usedPipes };
|
|
28137
|
+
return { expressions, symbols, nestingLevel, usedPipes, eagerPipes, deferBlocks };
|
|
27327
28138
|
}
|
|
27328
28139
|
ingest(template) {
|
|
27329
28140
|
if (template instanceof Template) {
|
|
@@ -27354,7 +28165,7 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
27354
28165
|
template.references.forEach(this.visitNode);
|
|
27355
28166
|
// Next, recurse into the template using its scope, and bumping the nesting level up by one.
|
|
27356
28167
|
const childScope = this.scope.getChildScope(template);
|
|
27357
|
-
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);
|
|
27358
28169
|
binder.ingest(template);
|
|
27359
28170
|
}
|
|
27360
28171
|
visitVariable(variable) {
|
|
@@ -27385,9 +28196,12 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
27385
28196
|
event.handler.visit(this);
|
|
27386
28197
|
}
|
|
27387
28198
|
visitDeferredBlock(deferred) {
|
|
28199
|
+
this.deferBlocks.add(deferred);
|
|
28200
|
+
this.isInDeferBlock = true;
|
|
28201
|
+
deferred.children.forEach(this.visitNode);
|
|
28202
|
+
this.isInDeferBlock = false;
|
|
27388
28203
|
deferred.triggers.forEach(this.visitNode);
|
|
27389
28204
|
deferred.prefetchTriggers.forEach(this.visitNode);
|
|
27390
|
-
deferred.children.forEach(this.visitNode);
|
|
27391
28205
|
deferred.placeholder && this.visitNode(deferred.placeholder);
|
|
27392
28206
|
deferred.loading && this.visitNode(deferred.loading);
|
|
27393
28207
|
deferred.error && this.visitNode(deferred.error);
|
|
@@ -27411,6 +28225,9 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
27411
28225
|
}
|
|
27412
28226
|
visitPipe(ast, context) {
|
|
27413
28227
|
this.usedPipes.add(ast.name);
|
|
28228
|
+
if (!this.isInDeferBlock) {
|
|
28229
|
+
this.eagerPipes.add(ast.name);
|
|
28230
|
+
}
|
|
27414
28231
|
return super.visitPipe(ast, context);
|
|
27415
28232
|
}
|
|
27416
28233
|
// These five types of AST expressions can refer to expression roots, which could be variables
|
|
@@ -27447,9 +28264,10 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
27447
28264
|
* See `BoundTarget` for documentation on the individual methods.
|
|
27448
28265
|
*/
|
|
27449
28266
|
class R3BoundTarget {
|
|
27450
|
-
constructor(target, directives, bindings, references, exprTargets, symbols, nestingLevel, templateEntities, usedPipes) {
|
|
28267
|
+
constructor(target, directives, eagerDirectives, bindings, references, exprTargets, symbols, nestingLevel, templateEntities, usedPipes, eagerPipes, deferredBlocks) {
|
|
27451
28268
|
this.target = target;
|
|
27452
28269
|
this.directives = directives;
|
|
28270
|
+
this.eagerDirectives = eagerDirectives;
|
|
27453
28271
|
this.bindings = bindings;
|
|
27454
28272
|
this.references = references;
|
|
27455
28273
|
this.exprTargets = exprTargets;
|
|
@@ -27457,6 +28275,8 @@ class R3BoundTarget {
|
|
|
27457
28275
|
this.nestingLevel = nestingLevel;
|
|
27458
28276
|
this.templateEntities = templateEntities;
|
|
27459
28277
|
this.usedPipes = usedPipes;
|
|
28278
|
+
this.eagerPipes = eagerPipes;
|
|
28279
|
+
this.deferredBlocks = deferredBlocks;
|
|
27460
28280
|
}
|
|
27461
28281
|
getEntitiesInTemplateScope(template) {
|
|
27462
28282
|
return this.templateEntities.get(template) ?? new Set();
|
|
@@ -27484,9 +28304,19 @@ class R3BoundTarget {
|
|
|
27484
28304
|
this.directives.forEach(dirs => dirs.forEach(dir => set.add(dir)));
|
|
27485
28305
|
return Array.from(set.values());
|
|
27486
28306
|
}
|
|
28307
|
+
getEagerlyUsedDirectives() {
|
|
28308
|
+
const set = new Set(this.eagerDirectives);
|
|
28309
|
+
return Array.from(set.values());
|
|
28310
|
+
}
|
|
27487
28311
|
getUsedPipes() {
|
|
27488
28312
|
return Array.from(this.usedPipes);
|
|
27489
28313
|
}
|
|
28314
|
+
getEagerlyUsedPipes() {
|
|
28315
|
+
return Array.from(this.eagerPipes);
|
|
28316
|
+
}
|
|
28317
|
+
getDeferBlocks() {
|
|
28318
|
+
return Array.from(this.deferredBlocks);
|
|
28319
|
+
}
|
|
27490
28320
|
}
|
|
27491
28321
|
function extractTemplateEntities(rootScope) {
|
|
27492
28322
|
const entityMap = new Map();
|
|
@@ -27544,7 +28374,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
|
|
|
27544
28374
|
function compileDeclareClassMetadata(metadata) {
|
|
27545
28375
|
const definitionMap = new DefinitionMap();
|
|
27546
28376
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
27547
|
-
definitionMap.set('version', literal('16.2.0-
|
|
28377
|
+
definitionMap.set('version', literal('16.2.0-rc.0'));
|
|
27548
28378
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
27549
28379
|
definitionMap.set('type', metadata.type);
|
|
27550
28380
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -27647,7 +28477,7 @@ function compileDeclareDirectiveFromMetadata(meta) {
|
|
|
27647
28477
|
function createDirectiveDefinitionMap(meta) {
|
|
27648
28478
|
const definitionMap = new DefinitionMap();
|
|
27649
28479
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
|
|
27650
|
-
definitionMap.set('version', literal('16.2.0-
|
|
28480
|
+
definitionMap.set('version', literal('16.2.0-rc.0'));
|
|
27651
28481
|
// e.g. `type: MyDirective`
|
|
27652
28482
|
definitionMap.set('type', meta.type.value);
|
|
27653
28483
|
if (meta.isStandalone) {
|
|
@@ -27875,7 +28705,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
27875
28705
|
function compileDeclareFactoryFunction(meta) {
|
|
27876
28706
|
const definitionMap = new DefinitionMap();
|
|
27877
28707
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
27878
|
-
definitionMap.set('version', literal('16.2.0-
|
|
28708
|
+
definitionMap.set('version', literal('16.2.0-rc.0'));
|
|
27879
28709
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
27880
28710
|
definitionMap.set('type', meta.type.value);
|
|
27881
28711
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -27910,7 +28740,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
27910
28740
|
function createInjectableDefinitionMap(meta) {
|
|
27911
28741
|
const definitionMap = new DefinitionMap();
|
|
27912
28742
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
27913
|
-
definitionMap.set('version', literal('16.2.0-
|
|
28743
|
+
definitionMap.set('version', literal('16.2.0-rc.0'));
|
|
27914
28744
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
27915
28745
|
definitionMap.set('type', meta.type.value);
|
|
27916
28746
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -27961,7 +28791,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
27961
28791
|
function createInjectorDefinitionMap(meta) {
|
|
27962
28792
|
const definitionMap = new DefinitionMap();
|
|
27963
28793
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
27964
|
-
definitionMap.set('version', literal('16.2.0-
|
|
28794
|
+
definitionMap.set('version', literal('16.2.0-rc.0'));
|
|
27965
28795
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
27966
28796
|
definitionMap.set('type', meta.type.value);
|
|
27967
28797
|
definitionMap.set('providers', meta.providers);
|
|
@@ -27994,7 +28824,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
27994
28824
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
27995
28825
|
}
|
|
27996
28826
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
27997
|
-
definitionMap.set('version', literal('16.2.0-
|
|
28827
|
+
definitionMap.set('version', literal('16.2.0-rc.0'));
|
|
27998
28828
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
27999
28829
|
definitionMap.set('type', meta.type.value);
|
|
28000
28830
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -28045,7 +28875,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
28045
28875
|
function createPipeDefinitionMap(meta) {
|
|
28046
28876
|
const definitionMap = new DefinitionMap();
|
|
28047
28877
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
28048
|
-
definitionMap.set('version', literal('16.2.0-
|
|
28878
|
+
definitionMap.set('version', literal('16.2.0-rc.0'));
|
|
28049
28879
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
28050
28880
|
// e.g. `type: MyPipe`
|
|
28051
28881
|
definitionMap.set('type', meta.type.value);
|
|
@@ -28078,5 +28908,5 @@ publishFacade(_global);
|
|
|
28078
28908
|
|
|
28079
28909
|
// This file is not used to build this module. It is only used during editing
|
|
28080
28910
|
|
|
28081
|
-
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 };
|
|
28082
28912
|
//# sourceMappingURL=compiler.mjs.map
|