@angular/compiler 16.2.1 → 17.0.0-next.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/compiler.mjs +3 -3
- package/esm2022/src/render3/partial/class_metadata.mjs +1 -1
- package/esm2022/src/render3/partial/component.mjs +4 -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_ast.mjs +113 -9
- package/esm2022/src/render3/r3_class_metadata_compiler.mjs +55 -1
- package/esm2022/src/render3/r3_control_flow.mjs +289 -0
- package/esm2022/src/render3/r3_deferred_blocks.mjs +16 -9
- package/esm2022/src/render3/r3_deferred_triggers.mjs +33 -19
- package/esm2022/src/render3/r3_identifiers.mjs +17 -1
- package/esm2022/src/render3/r3_template_transform.mjs +28 -7
- package/esm2022/src/render3/view/api.mjs +1 -1
- package/esm2022/src/render3/view/compiler.mjs +12 -2
- package/esm2022/src/render3/view/t2_binder.mjs +66 -5
- package/esm2022/src/render3/view/template.mjs +130 -54
- package/esm2022/src/template/pipeline/ir/index.mjs +2 -3
- package/esm2022/src/template/pipeline/ir/src/enums.mjs +41 -3
- package/esm2022/src/template/pipeline/ir/src/expression.mjs +11 -1
- package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +16 -4
- package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +5 -3
- package/esm2022/src/template/pipeline/src/emit.mjs +3 -1
- package/esm2022/src/template/pipeline/src/ingest.mjs +10 -10
- package/esm2022/src/template/pipeline/src/phases/attribute_extraction.mjs +43 -75
- package/esm2022/src/template/pipeline/src/phases/binding_specialization.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/const_collection.mjs +90 -13
- package/esm2022/src/template/pipeline/src/phases/parse_extracted_styles.mjs +38 -0
- package/esm2022/src/version.mjs +1 -1
- package/fesm2022/compiler.mjs +1110 -425
- package/fesm2022/compiler.mjs.map +1 -1
- package/fesm2022/testing.mjs +1 -1
- package/index.d.ts +141 -5
- package/package.json +2 -2
- package/testing/index.d.ts +1 -1
- package/esm2022/src/template/pipeline/ir/src/element.mjs +0 -108
package/fesm2022/compiler.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular
|
|
2
|
+
* @license Angular v17.0.0-next.0
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -2614,6 +2614,20 @@ class Identifiers {
|
|
|
2614
2614
|
static { this.resetView = { name: 'ɵɵresetView', moduleName: CORE }; }
|
|
2615
2615
|
static { this.templateCreate = { name: 'ɵɵtemplate', moduleName: CORE }; }
|
|
2616
2616
|
static { this.defer = { name: 'ɵɵdefer', moduleName: CORE }; }
|
|
2617
|
+
static { this.deferWhen = { name: 'ɵɵdeferWhen', moduleName: CORE }; }
|
|
2618
|
+
static { this.deferOnIdle = { name: 'ɵɵdeferOnIdle', moduleName: CORE }; }
|
|
2619
|
+
static { this.deferOnImmediate = { name: 'ɵɵdeferOnImmediate', moduleName: CORE }; }
|
|
2620
|
+
static { this.deferOnTimer = { name: 'ɵɵdeferOnTimer', moduleName: CORE }; }
|
|
2621
|
+
static { this.deferOnHover = { name: 'ɵɵdeferOnHover', moduleName: CORE }; }
|
|
2622
|
+
static { this.deferOnInteraction = { name: 'ɵɵdeferOnInteraction', moduleName: CORE }; }
|
|
2623
|
+
static { this.deferOnViewport = { name: 'ɵɵdeferOnViewport', moduleName: CORE }; }
|
|
2624
|
+
static { this.deferPrefetchWhen = { name: 'ɵɵdeferPrefetchWhen', moduleName: CORE }; }
|
|
2625
|
+
static { this.deferPrefetchOnIdle = { name: 'ɵɵdeferPrefetchOnIdle', moduleName: CORE }; }
|
|
2626
|
+
static { this.deferPrefetchOnImmediate = { name: 'ɵɵdeferPrefetchOnImmediate', moduleName: CORE }; }
|
|
2627
|
+
static { this.deferPrefetchOnTimer = { name: 'ɵɵdeferPrefetchOnTimer', moduleName: CORE }; }
|
|
2628
|
+
static { this.deferPrefetchOnHover = { name: 'ɵɵdeferPrefetchOnHover', moduleName: CORE }; }
|
|
2629
|
+
static { this.deferPrefetchOnInteraction = { name: 'ɵɵdeferPrefetchOnInteraction', moduleName: CORE }; }
|
|
2630
|
+
static { this.deferPrefetchOnViewport = { name: 'ɵɵdeferPrefetchOnViewport', moduleName: CORE }; }
|
|
2617
2631
|
static { this.text = { name: 'ɵɵtext', moduleName: CORE }; }
|
|
2618
2632
|
static { this.enableBindings = { name: 'ɵɵenableBindings', moduleName: CORE }; }
|
|
2619
2633
|
static { this.disableBindings = { name: 'ɵɵdisableBindings', moduleName: CORE }; }
|
|
@@ -2681,6 +2695,7 @@ class Identifiers {
|
|
|
2681
2695
|
static { this.resolveWindow = { name: 'ɵɵresolveWindow', moduleName: CORE }; }
|
|
2682
2696
|
static { this.resolveDocument = { name: 'ɵɵresolveDocument', moduleName: CORE }; }
|
|
2683
2697
|
static { this.resolveBody = { name: 'ɵɵresolveBody', moduleName: CORE }; }
|
|
2698
|
+
static { this.getComponentDepsFactory = { name: 'ɵɵgetComponentDepsFactory', moduleName: CORE }; }
|
|
2684
2699
|
static { this.defineComponent = { name: 'ɵɵdefineComponent', moduleName: CORE }; }
|
|
2685
2700
|
static { this.declareComponent = { name: 'ɵɵngDeclareComponent', moduleName: CORE }; }
|
|
2686
2701
|
static { this.setComponentScope = { name: 'ɵɵsetComponentScope', moduleName: CORE }; }
|
|
@@ -2729,6 +2744,7 @@ class Identifiers {
|
|
|
2729
2744
|
static { this.declarePipe = { name: 'ɵɵngDeclarePipe', moduleName: CORE }; }
|
|
2730
2745
|
static { this.declareClassMetadata = { name: 'ɵɵngDeclareClassMetadata', moduleName: CORE }; }
|
|
2731
2746
|
static { this.setClassMetadata = { name: 'ɵsetClassMetadata', moduleName: CORE }; }
|
|
2747
|
+
static { this.setClassMetadataAsync = { name: 'ɵsetClassMetadataAsync', moduleName: CORE }; }
|
|
2732
2748
|
static { this.queryRefresh = { name: 'ɵɵqueryRefresh', moduleName: CORE }; }
|
|
2733
2749
|
static { this.viewQuery = { name: 'ɵɵviewQuery', moduleName: CORE }; }
|
|
2734
2750
|
static { this.loadQuery = { name: 'ɵɵloadQuery', moduleName: CORE }; }
|
|
@@ -3983,18 +3999,108 @@ class DeferredBlockError {
|
|
|
3983
3999
|
class DeferredBlock {
|
|
3984
4000
|
constructor(children, triggers, prefetchTriggers, placeholder, loading, error, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3985
4001
|
this.children = children;
|
|
3986
|
-
this.triggers = triggers;
|
|
3987
|
-
this.prefetchTriggers = prefetchTriggers;
|
|
3988
4002
|
this.placeholder = placeholder;
|
|
3989
4003
|
this.loading = loading;
|
|
3990
4004
|
this.error = error;
|
|
3991
4005
|
this.sourceSpan = sourceSpan;
|
|
3992
4006
|
this.startSourceSpan = startSourceSpan;
|
|
3993
4007
|
this.endSourceSpan = endSourceSpan;
|
|
4008
|
+
this.triggers = triggers;
|
|
4009
|
+
this.prefetchTriggers = prefetchTriggers;
|
|
4010
|
+
// We cache the keys since we know that they won't change and we
|
|
4011
|
+
// don't want to enumarate them every time we're traversing the AST.
|
|
4012
|
+
this.definedTriggers = Object.keys(triggers);
|
|
4013
|
+
this.definedPrefetchTriggers = Object.keys(prefetchTriggers);
|
|
3994
4014
|
}
|
|
3995
4015
|
visit(visitor) {
|
|
3996
4016
|
return visitor.visitDeferredBlock(this);
|
|
3997
4017
|
}
|
|
4018
|
+
visitAll(visitor) {
|
|
4019
|
+
this.visitTriggers(this.definedTriggers, this.triggers, visitor);
|
|
4020
|
+
this.visitTriggers(this.definedPrefetchTriggers, this.prefetchTriggers, visitor);
|
|
4021
|
+
visitAll$1(visitor, this.children);
|
|
4022
|
+
this.placeholder && visitor.visitDeferredBlockPlaceholder(this.placeholder);
|
|
4023
|
+
this.loading && visitor.visitDeferredBlockLoading(this.loading);
|
|
4024
|
+
this.error && visitor.visitDeferredBlockError(this.error);
|
|
4025
|
+
}
|
|
4026
|
+
visitTriggers(keys, triggers, visitor) {
|
|
4027
|
+
for (const key of keys) {
|
|
4028
|
+
visitor.visitDeferredTrigger(triggers[key]);
|
|
4029
|
+
}
|
|
4030
|
+
}
|
|
4031
|
+
}
|
|
4032
|
+
class SwitchBlock {
|
|
4033
|
+
constructor(expression, cases, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
4034
|
+
this.expression = expression;
|
|
4035
|
+
this.cases = cases;
|
|
4036
|
+
this.sourceSpan = sourceSpan;
|
|
4037
|
+
this.startSourceSpan = startSourceSpan;
|
|
4038
|
+
this.endSourceSpan = endSourceSpan;
|
|
4039
|
+
}
|
|
4040
|
+
visit(visitor) {
|
|
4041
|
+
return visitor.visitSwitchBlock(this);
|
|
4042
|
+
}
|
|
4043
|
+
}
|
|
4044
|
+
class SwitchBlockCase {
|
|
4045
|
+
constructor(expression, children, sourceSpan, startSourceSpan) {
|
|
4046
|
+
this.expression = expression;
|
|
4047
|
+
this.children = children;
|
|
4048
|
+
this.sourceSpan = sourceSpan;
|
|
4049
|
+
this.startSourceSpan = startSourceSpan;
|
|
4050
|
+
}
|
|
4051
|
+
visit(visitor) {
|
|
4052
|
+
return visitor.visitSwitchBlockCase(this);
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
4055
|
+
class ForLoopBlock {
|
|
4056
|
+
constructor(itemName, expression,
|
|
4057
|
+
// TODO(crisbeto): figure out if trackBy should be an AST
|
|
4058
|
+
trackBy, children, empty, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
4059
|
+
this.itemName = itemName;
|
|
4060
|
+
this.expression = expression;
|
|
4061
|
+
this.trackBy = trackBy;
|
|
4062
|
+
this.children = children;
|
|
4063
|
+
this.empty = empty;
|
|
4064
|
+
this.sourceSpan = sourceSpan;
|
|
4065
|
+
this.startSourceSpan = startSourceSpan;
|
|
4066
|
+
this.endSourceSpan = endSourceSpan;
|
|
4067
|
+
}
|
|
4068
|
+
visit(visitor) {
|
|
4069
|
+
return visitor.visitForLoopBlock(this);
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
class ForLoopBlockEmpty {
|
|
4073
|
+
constructor(children, sourceSpan, startSourceSpan) {
|
|
4074
|
+
this.children = children;
|
|
4075
|
+
this.sourceSpan = sourceSpan;
|
|
4076
|
+
this.startSourceSpan = startSourceSpan;
|
|
4077
|
+
}
|
|
4078
|
+
visit(visitor) {
|
|
4079
|
+
return visitor.visitForLoopBlockEmpty(this);
|
|
4080
|
+
}
|
|
4081
|
+
}
|
|
4082
|
+
class IfBlock {
|
|
4083
|
+
constructor(branches, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
4084
|
+
this.branches = branches;
|
|
4085
|
+
this.sourceSpan = sourceSpan;
|
|
4086
|
+
this.startSourceSpan = startSourceSpan;
|
|
4087
|
+
this.endSourceSpan = endSourceSpan;
|
|
4088
|
+
}
|
|
4089
|
+
visit(visitor) {
|
|
4090
|
+
return visitor.visitIfBlock(this);
|
|
4091
|
+
}
|
|
4092
|
+
}
|
|
4093
|
+
class IfBlockBranch {
|
|
4094
|
+
constructor(expression, children, expressionAlias, sourceSpan, startSourceSpan) {
|
|
4095
|
+
this.expression = expression;
|
|
4096
|
+
this.children = children;
|
|
4097
|
+
this.expressionAlias = expressionAlias;
|
|
4098
|
+
this.sourceSpan = sourceSpan;
|
|
4099
|
+
this.startSourceSpan = startSourceSpan;
|
|
4100
|
+
}
|
|
4101
|
+
visit(visitor) {
|
|
4102
|
+
return visitor.visitIfBlockBranch(this);
|
|
4103
|
+
}
|
|
3998
4104
|
}
|
|
3999
4105
|
class Template {
|
|
4000
4106
|
constructor(
|
|
@@ -4084,12 +4190,7 @@ class RecursiveVisitor$1 {
|
|
|
4084
4190
|
visitAll$1(this, template.variables);
|
|
4085
4191
|
}
|
|
4086
4192
|
visitDeferredBlock(deferred) {
|
|
4087
|
-
visitAll
|
|
4088
|
-
visitAll$1(this, deferred.prefetchTriggers);
|
|
4089
|
-
visitAll$1(this, deferred.children);
|
|
4090
|
-
deferred.placeholder?.visit(this);
|
|
4091
|
-
deferred.loading?.visit(this);
|
|
4092
|
-
deferred.error?.visit(this);
|
|
4193
|
+
deferred.visitAll(this);
|
|
4093
4194
|
}
|
|
4094
4195
|
visitDeferredBlockPlaceholder(block) {
|
|
4095
4196
|
visitAll$1(this, block.children);
|
|
@@ -4100,6 +4201,25 @@ class RecursiveVisitor$1 {
|
|
|
4100
4201
|
visitDeferredBlockLoading(block) {
|
|
4101
4202
|
visitAll$1(this, block.children);
|
|
4102
4203
|
}
|
|
4204
|
+
visitSwitchBlock(block) {
|
|
4205
|
+
visitAll$1(this, block.cases);
|
|
4206
|
+
}
|
|
4207
|
+
visitSwitchBlockCase(block) {
|
|
4208
|
+
visitAll$1(this, block.children);
|
|
4209
|
+
}
|
|
4210
|
+
visitForLoopBlock(block) {
|
|
4211
|
+
visitAll$1(this, block.children);
|
|
4212
|
+
block.empty?.visit(this);
|
|
4213
|
+
}
|
|
4214
|
+
visitForLoopBlockEmpty(block) {
|
|
4215
|
+
visitAll$1(this, block.children);
|
|
4216
|
+
}
|
|
4217
|
+
visitIfBlock(block) {
|
|
4218
|
+
visitAll$1(this, block.branches);
|
|
4219
|
+
}
|
|
4220
|
+
visitIfBlockBranch(block) {
|
|
4221
|
+
visitAll$1(this, block.children);
|
|
4222
|
+
}
|
|
4103
4223
|
visitContent(content) { }
|
|
4104
4224
|
visitVariable(variable) { }
|
|
4105
4225
|
visitReference(reference) { }
|
|
@@ -8615,140 +8735,6 @@ function repeatGroups(groups, multiples) {
|
|
|
8615
8735
|
}
|
|
8616
8736
|
}
|
|
8617
8737
|
|
|
8618
|
-
var TagContentType;
|
|
8619
|
-
(function (TagContentType) {
|
|
8620
|
-
TagContentType[TagContentType["RAW_TEXT"] = 0] = "RAW_TEXT";
|
|
8621
|
-
TagContentType[TagContentType["ESCAPABLE_RAW_TEXT"] = 1] = "ESCAPABLE_RAW_TEXT";
|
|
8622
|
-
TagContentType[TagContentType["PARSABLE_DATA"] = 2] = "PARSABLE_DATA";
|
|
8623
|
-
})(TagContentType || (TagContentType = {}));
|
|
8624
|
-
function splitNsName(elementName) {
|
|
8625
|
-
if (elementName[0] != ':') {
|
|
8626
|
-
return [null, elementName];
|
|
8627
|
-
}
|
|
8628
|
-
const colonIndex = elementName.indexOf(':', 1);
|
|
8629
|
-
if (colonIndex === -1) {
|
|
8630
|
-
throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
|
|
8631
|
-
}
|
|
8632
|
-
return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
|
|
8633
|
-
}
|
|
8634
|
-
// `<ng-container>` tags work the same regardless the namespace
|
|
8635
|
-
function isNgContainer(tagName) {
|
|
8636
|
-
return splitNsName(tagName)[1] === 'ng-container';
|
|
8637
|
-
}
|
|
8638
|
-
// `<ng-content>` tags work the same regardless the namespace
|
|
8639
|
-
function isNgContent(tagName) {
|
|
8640
|
-
return splitNsName(tagName)[1] === 'ng-content';
|
|
8641
|
-
}
|
|
8642
|
-
// `<ng-template>` tags work the same regardless the namespace
|
|
8643
|
-
function isNgTemplate(tagName) {
|
|
8644
|
-
return splitNsName(tagName)[1] === 'ng-template';
|
|
8645
|
-
}
|
|
8646
|
-
function getNsPrefix(fullName) {
|
|
8647
|
-
return fullName === null ? null : splitNsName(fullName)[0];
|
|
8648
|
-
}
|
|
8649
|
-
function mergeNsAndName(prefix, localName) {
|
|
8650
|
-
return prefix ? `:${prefix}:${localName}` : localName;
|
|
8651
|
-
}
|
|
8652
|
-
|
|
8653
|
-
/**
|
|
8654
|
-
* Enumeration of the types of attributes which can be applied to an element.
|
|
8655
|
-
*/
|
|
8656
|
-
var BindingKind;
|
|
8657
|
-
(function (BindingKind) {
|
|
8658
|
-
/**
|
|
8659
|
-
* Static attributes.
|
|
8660
|
-
*/
|
|
8661
|
-
BindingKind[BindingKind["Attribute"] = 0] = "Attribute";
|
|
8662
|
-
/**
|
|
8663
|
-
* Class bindings.
|
|
8664
|
-
*/
|
|
8665
|
-
BindingKind[BindingKind["ClassName"] = 1] = "ClassName";
|
|
8666
|
-
/**
|
|
8667
|
-
* Style bindings.
|
|
8668
|
-
*/
|
|
8669
|
-
BindingKind[BindingKind["StyleProperty"] = 2] = "StyleProperty";
|
|
8670
|
-
/**
|
|
8671
|
-
* Dynamic property bindings.
|
|
8672
|
-
*/
|
|
8673
|
-
BindingKind[BindingKind["Property"] = 3] = "Property";
|
|
8674
|
-
/**
|
|
8675
|
-
* Property or attribute bindings on a template.
|
|
8676
|
-
*/
|
|
8677
|
-
BindingKind[BindingKind["Template"] = 4] = "Template";
|
|
8678
|
-
/**
|
|
8679
|
-
* Internationalized attributes.
|
|
8680
|
-
*/
|
|
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 = {}));
|
|
8687
|
-
const FLYWEIGHT_ARRAY = Object.freeze([]);
|
|
8688
|
-
/**
|
|
8689
|
-
* Container for all of the various kinds of attributes which are applied on an element.
|
|
8690
|
-
*/
|
|
8691
|
-
class ElementAttributes {
|
|
8692
|
-
constructor() {
|
|
8693
|
-
this.known = new Set();
|
|
8694
|
-
this.byKind = new Map;
|
|
8695
|
-
this.projectAs = null;
|
|
8696
|
-
}
|
|
8697
|
-
get attributes() {
|
|
8698
|
-
return this.byKind.get(BindingKind.Attribute) ?? FLYWEIGHT_ARRAY;
|
|
8699
|
-
}
|
|
8700
|
-
get classes() {
|
|
8701
|
-
return this.byKind.get(BindingKind.ClassName) ?? FLYWEIGHT_ARRAY;
|
|
8702
|
-
}
|
|
8703
|
-
get styles() {
|
|
8704
|
-
return this.byKind.get(BindingKind.StyleProperty) ?? FLYWEIGHT_ARRAY;
|
|
8705
|
-
}
|
|
8706
|
-
get bindings() {
|
|
8707
|
-
return this.byKind.get(BindingKind.Property) ?? FLYWEIGHT_ARRAY;
|
|
8708
|
-
}
|
|
8709
|
-
get template() {
|
|
8710
|
-
return this.byKind.get(BindingKind.Template) ?? FLYWEIGHT_ARRAY;
|
|
8711
|
-
}
|
|
8712
|
-
get i18n() {
|
|
8713
|
-
return this.byKind.get(BindingKind.I18n) ?? FLYWEIGHT_ARRAY;
|
|
8714
|
-
}
|
|
8715
|
-
add(kind, name, value) {
|
|
8716
|
-
if (this.known.has(name)) {
|
|
8717
|
-
return;
|
|
8718
|
-
}
|
|
8719
|
-
this.known.add(name);
|
|
8720
|
-
const array = this.arrayFor(kind);
|
|
8721
|
-
array.push(...getAttributeNameLiterals$1(name));
|
|
8722
|
-
if (kind === BindingKind.Attribute || kind === BindingKind.StyleProperty) {
|
|
8723
|
-
if (value === null) {
|
|
8724
|
-
throw Error('Attribute & style element attributes must have a value');
|
|
8725
|
-
}
|
|
8726
|
-
array.push(value);
|
|
8727
|
-
}
|
|
8728
|
-
}
|
|
8729
|
-
arrayFor(kind) {
|
|
8730
|
-
if (!this.byKind.has(kind)) {
|
|
8731
|
-
this.byKind.set(kind, []);
|
|
8732
|
-
}
|
|
8733
|
-
return this.byKind.get(kind);
|
|
8734
|
-
}
|
|
8735
|
-
}
|
|
8736
|
-
function getAttributeNameLiterals$1(name) {
|
|
8737
|
-
const [attributeNamespace, attributeName] = splitNsName(name);
|
|
8738
|
-
const nameLiteral = literal(attributeName);
|
|
8739
|
-
if (attributeNamespace) {
|
|
8740
|
-
return [
|
|
8741
|
-
literal(0 /* core.AttributeMarker.NamespaceURI */), literal(attributeNamespace), nameLiteral
|
|
8742
|
-
];
|
|
8743
|
-
}
|
|
8744
|
-
return [nameLiteral];
|
|
8745
|
-
}
|
|
8746
|
-
function assertIsElementAttributes(attrs) {
|
|
8747
|
-
if (!(attrs instanceof ElementAttributes)) {
|
|
8748
|
-
throw new Error(`AssertionError: ElementAttributes has already been coalesced into the view constants`);
|
|
8749
|
-
}
|
|
8750
|
-
}
|
|
8751
|
-
|
|
8752
8738
|
/**
|
|
8753
8739
|
* Distinguishes different kinds of IR operations.
|
|
8754
8740
|
*
|
|
@@ -8855,14 +8841,18 @@ var OpKind;
|
|
|
8855
8841
|
* An operation to associate an attribute with an element.
|
|
8856
8842
|
*/
|
|
8857
8843
|
OpKind[OpKind["Attribute"] = 23] = "Attribute";
|
|
8844
|
+
/**
|
|
8845
|
+
* An attribute that has been extracted for inclusion in the consts array.
|
|
8846
|
+
*/
|
|
8847
|
+
OpKind[OpKind["ExtractedAttribute"] = 24] = "ExtractedAttribute";
|
|
8858
8848
|
/**
|
|
8859
8849
|
* A host binding property.
|
|
8860
8850
|
*/
|
|
8861
|
-
OpKind[OpKind["HostProperty"] =
|
|
8851
|
+
OpKind[OpKind["HostProperty"] = 25] = "HostProperty";
|
|
8862
8852
|
/**
|
|
8863
8853
|
* A namespace change, which causes the subsequent elements to be processed as either HTML or SVG.
|
|
8864
8854
|
*/
|
|
8865
|
-
OpKind[OpKind["Namespace"] =
|
|
8855
|
+
OpKind[OpKind["Namespace"] = 26] = "Namespace";
|
|
8866
8856
|
// TODO: Add Host Listeners, and possibly other host ops also.
|
|
8867
8857
|
})(OpKind || (OpKind = {}));
|
|
8868
8858
|
/**
|
|
@@ -8991,6 +8981,40 @@ var SanitizerFn;
|
|
|
8991
8981
|
SanitizerFn[SanitizerFn["ResourceUrl"] = 4] = "ResourceUrl";
|
|
8992
8982
|
SanitizerFn[SanitizerFn["IframeAttribute"] = 5] = "IframeAttribute";
|
|
8993
8983
|
})(SanitizerFn || (SanitizerFn = {}));
|
|
8984
|
+
/**
|
|
8985
|
+
* Enumeration of the types of attributes which can be applied to an element.
|
|
8986
|
+
*/
|
|
8987
|
+
var BindingKind;
|
|
8988
|
+
(function (BindingKind) {
|
|
8989
|
+
/**
|
|
8990
|
+
* Static attributes.
|
|
8991
|
+
*/
|
|
8992
|
+
BindingKind[BindingKind["Attribute"] = 0] = "Attribute";
|
|
8993
|
+
/**
|
|
8994
|
+
* Class bindings.
|
|
8995
|
+
*/
|
|
8996
|
+
BindingKind[BindingKind["ClassName"] = 1] = "ClassName";
|
|
8997
|
+
/**
|
|
8998
|
+
* Style bindings.
|
|
8999
|
+
*/
|
|
9000
|
+
BindingKind[BindingKind["StyleProperty"] = 2] = "StyleProperty";
|
|
9001
|
+
/**
|
|
9002
|
+
* Dynamic property bindings.
|
|
9003
|
+
*/
|
|
9004
|
+
BindingKind[BindingKind["Property"] = 3] = "Property";
|
|
9005
|
+
/**
|
|
9006
|
+
* Property or attribute bindings on a template.
|
|
9007
|
+
*/
|
|
9008
|
+
BindingKind[BindingKind["Template"] = 4] = "Template";
|
|
9009
|
+
/**
|
|
9010
|
+
* Internationalized attributes.
|
|
9011
|
+
*/
|
|
9012
|
+
BindingKind[BindingKind["I18n"] = 5] = "I18n";
|
|
9013
|
+
/**
|
|
9014
|
+
* Animation property bindings.
|
|
9015
|
+
*/
|
|
9016
|
+
BindingKind[BindingKind["Animation"] = 6] = "Animation";
|
|
9017
|
+
})(BindingKind || (BindingKind = {}));
|
|
8994
9018
|
|
|
8995
9019
|
/**
|
|
8996
9020
|
* Marker symbol for `ConsumesSlotOpTrait`.
|
|
@@ -9133,7 +9157,7 @@ class Interpolation {
|
|
|
9133
9157
|
/**
|
|
9134
9158
|
* Create a `BindingOp`, not yet transformed into a particular type of binding.
|
|
9135
9159
|
*/
|
|
9136
|
-
function createBindingOp(target, kind, name, expression, unit, securityContext, isTemplate, sourceSpan) {
|
|
9160
|
+
function createBindingOp(target, kind, name, expression, unit, securityContext, isTextAttribute, isTemplate, sourceSpan) {
|
|
9137
9161
|
return {
|
|
9138
9162
|
kind: OpKind.Binding,
|
|
9139
9163
|
bindingKind: kind,
|
|
@@ -9142,6 +9166,7 @@ function createBindingOp(target, kind, name, expression, unit, securityContext,
|
|
|
9142
9166
|
expression,
|
|
9143
9167
|
unit,
|
|
9144
9168
|
securityContext,
|
|
9169
|
+
isTextAttribute,
|
|
9145
9170
|
isTemplate,
|
|
9146
9171
|
sourceSpan,
|
|
9147
9172
|
...NEW_OP,
|
|
@@ -9224,7 +9249,7 @@ function createClassMapOp(xref, expression, sourceSpan) {
|
|
|
9224
9249
|
/**
|
|
9225
9250
|
* Create an `AttributeOp`.
|
|
9226
9251
|
*/
|
|
9227
|
-
function createAttributeOp(target, name, expression, securityContext, isTemplate, sourceSpan) {
|
|
9252
|
+
function createAttributeOp(target, name, expression, securityContext, isTextAttribute, isTemplate, sourceSpan) {
|
|
9228
9253
|
return {
|
|
9229
9254
|
kind: OpKind.Attribute,
|
|
9230
9255
|
target,
|
|
@@ -9232,6 +9257,7 @@ function createAttributeOp(target, name, expression, securityContext, isTemplate
|
|
|
9232
9257
|
expression,
|
|
9233
9258
|
securityContext,
|
|
9234
9259
|
sanitizer: null,
|
|
9260
|
+
isTextAttribute,
|
|
9235
9261
|
isTemplate,
|
|
9236
9262
|
sourceSpan,
|
|
9237
9263
|
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
@@ -9861,6 +9887,10 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
9861
9887
|
transformExpressionsInOp(innerOp, transform, flags | VisitorContextFlag.InChildOperation);
|
|
9862
9888
|
}
|
|
9863
9889
|
break;
|
|
9890
|
+
case OpKind.ExtractedAttribute:
|
|
9891
|
+
op.expression =
|
|
9892
|
+
op.expression && transformExpressionsInExpression(op.expression, transform, flags);
|
|
9893
|
+
break;
|
|
9864
9894
|
case OpKind.Element:
|
|
9865
9895
|
case OpKind.ElementStart:
|
|
9866
9896
|
case OpKind.ElementEnd:
|
|
@@ -9965,6 +9995,12 @@ function transformExpressionsInStatement(stmt, transform, flags) {
|
|
|
9965
9995
|
throw new Error(`Unhandled statement kind: ${stmt.constructor.name}`);
|
|
9966
9996
|
}
|
|
9967
9997
|
}
|
|
9998
|
+
/**
|
|
9999
|
+
* Checks whether the given expression is a string literal.
|
|
10000
|
+
*/
|
|
10001
|
+
function isStringLiteral(expr) {
|
|
10002
|
+
return expr instanceof LiteralExpr && typeof expr.value === 'string';
|
|
10003
|
+
}
|
|
9968
10004
|
|
|
9969
10005
|
/**
|
|
9970
10006
|
* A linked list of `Op` nodes of a given subtype.
|
|
@@ -10227,7 +10263,7 @@ function createElementStartOp(tag, xref, namespace, sourceSpan) {
|
|
|
10227
10263
|
kind: OpKind.ElementStart,
|
|
10228
10264
|
xref,
|
|
10229
10265
|
tag,
|
|
10230
|
-
attributes:
|
|
10266
|
+
attributes: null,
|
|
10231
10267
|
localRefs: [],
|
|
10232
10268
|
nonBindable: false,
|
|
10233
10269
|
namespace,
|
|
@@ -10243,7 +10279,7 @@ function createTemplateOp(xref, tag, namespace, sourceSpan) {
|
|
|
10243
10279
|
return {
|
|
10244
10280
|
kind: OpKind.Template,
|
|
10245
10281
|
xref,
|
|
10246
|
-
attributes:
|
|
10282
|
+
attributes: null,
|
|
10247
10283
|
tag,
|
|
10248
10284
|
decls: null,
|
|
10249
10285
|
vars: null,
|
|
@@ -10354,6 +10390,19 @@ function createNamespaceOp(namespace) {
|
|
|
10354
10390
|
...NEW_OP,
|
|
10355
10391
|
};
|
|
10356
10392
|
}
|
|
10393
|
+
/**
|
|
10394
|
+
* Create an `ExtractedAttributeOp`.
|
|
10395
|
+
*/
|
|
10396
|
+
function createExtractedAttributeOp(target, bindingKind, name, expression) {
|
|
10397
|
+
return {
|
|
10398
|
+
kind: OpKind.ExtractedAttribute,
|
|
10399
|
+
target,
|
|
10400
|
+
bindingKind,
|
|
10401
|
+
name,
|
|
10402
|
+
expression,
|
|
10403
|
+
...NEW_OP,
|
|
10404
|
+
};
|
|
10405
|
+
}
|
|
10357
10406
|
|
|
10358
10407
|
function createHostPropertyOp(name, expression, sourceSpan) {
|
|
10359
10408
|
return {
|
|
@@ -10663,86 +10712,7 @@ function removeAnys(e) {
|
|
|
10663
10712
|
}
|
|
10664
10713
|
|
|
10665
10714
|
/**
|
|
10666
|
-
*
|
|
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']`
|
|
10672
|
-
*/
|
|
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);
|
|
10733
|
-
}
|
|
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();
|
|
10742
|
-
}
|
|
10743
|
-
|
|
10744
|
-
/**
|
|
10745
|
-
* Gets a map of all elements in the given view by their xref id.
|
|
10715
|
+
* Gets a map of all elements in the given view by their xref id.
|
|
10746
10716
|
*/
|
|
10747
10717
|
function getElementsByXrefId(view) {
|
|
10748
10718
|
const elements = new Map();
|
|
@@ -10756,12 +10726,39 @@ function getElementsByXrefId(view) {
|
|
|
10756
10726
|
}
|
|
10757
10727
|
|
|
10758
10728
|
/**
|
|
10759
|
-
* Find all attribute and binding ops, and
|
|
10729
|
+
* Find all extractable attribute and binding ops, and create ExtractedAttributeOps for them.
|
|
10760
10730
|
* In cases where no instruction needs to be generated for the attribute or binding, it is removed.
|
|
10761
10731
|
*/
|
|
10762
10732
|
function phaseAttributeExtraction(cpl) {
|
|
10763
10733
|
for (const [_, view] of cpl.views) {
|
|
10764
|
-
|
|
10734
|
+
const elements = getElementsByXrefId(view);
|
|
10735
|
+
for (const op of view.ops()) {
|
|
10736
|
+
switch (op.kind) {
|
|
10737
|
+
case OpKind.Attribute:
|
|
10738
|
+
extractAttributeOp(view, op, elements);
|
|
10739
|
+
break;
|
|
10740
|
+
case OpKind.Property:
|
|
10741
|
+
if (!op.isAnimationTrigger) {
|
|
10742
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, op.isTemplate ? BindingKind.Template : BindingKind.Property, op.name, null), lookupElement$2(elements, op.target));
|
|
10743
|
+
}
|
|
10744
|
+
break;
|
|
10745
|
+
case OpKind.StyleProp:
|
|
10746
|
+
case OpKind.ClassProp:
|
|
10747
|
+
// The old compiler treated empty style bindings as regular bindings for the purpose of
|
|
10748
|
+
// directive matching. That behavior is incorrect, but we emulate it in compatibility
|
|
10749
|
+
// mode.
|
|
10750
|
+
if (view.compatibility === CompatibilityMode.TemplateDefinitionBuilder &&
|
|
10751
|
+
op.expression instanceof EmptyExpr) {
|
|
10752
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.Property, op.name, null), lookupElement$2(elements, op.target));
|
|
10753
|
+
}
|
|
10754
|
+
break;
|
|
10755
|
+
case OpKind.Listener:
|
|
10756
|
+
if (!op.isAnimationListener) {
|
|
10757
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.Property, op.name, null), lookupElement$2(elements, op.target));
|
|
10758
|
+
}
|
|
10759
|
+
break;
|
|
10760
|
+
}
|
|
10761
|
+
}
|
|
10765
10762
|
}
|
|
10766
10763
|
}
|
|
10767
10764
|
/**
|
|
@@ -10775,84 +10772,28 @@ function lookupElement$2(elements, xref) {
|
|
|
10775
10772
|
return el;
|
|
10776
10773
|
}
|
|
10777
10774
|
/**
|
|
10778
|
-
*
|
|
10779
|
-
* not need further processing.
|
|
10775
|
+
* Extracts an attribute binding.
|
|
10780
10776
|
*/
|
|
10781
|
-
function populateElementAttributes(view) {
|
|
10782
|
-
const elements = getElementsByXrefId(view);
|
|
10783
|
-
for (const op of view.ops()) {
|
|
10784
|
-
let ownerOp;
|
|
10785
|
-
switch (op.kind) {
|
|
10786
|
-
case OpKind.Attribute:
|
|
10787
|
-
extractAttributeOp(view, op, elements);
|
|
10788
|
-
break;
|
|
10789
|
-
case OpKind.Property:
|
|
10790
|
-
if (op.isAnimationTrigger) {
|
|
10791
|
-
continue; // Don't extract animation properties.
|
|
10792
|
-
}
|
|
10793
|
-
ownerOp = lookupElement$2(elements, op.target);
|
|
10794
|
-
assertIsElementAttributes(ownerOp.attributes);
|
|
10795
|
-
ownerOp.attributes.add(op.isTemplate ? BindingKind.Template : BindingKind.Property, op.name, null);
|
|
10796
|
-
break;
|
|
10797
|
-
case OpKind.StyleProp:
|
|
10798
|
-
case OpKind.ClassProp:
|
|
10799
|
-
ownerOp = lookupElement$2(elements, op.target);
|
|
10800
|
-
assertIsElementAttributes(ownerOp.attributes);
|
|
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);
|
|
10809
|
-
}
|
|
10810
|
-
break;
|
|
10811
|
-
case OpKind.Listener:
|
|
10812
|
-
if (op.isAnimationListener) {
|
|
10813
|
-
continue; // Don't extract animation listeners.
|
|
10814
|
-
}
|
|
10815
|
-
ownerOp = lookupElement$2(elements, op.target);
|
|
10816
|
-
assertIsElementAttributes(ownerOp.attributes);
|
|
10817
|
-
ownerOp.attributes.add(BindingKind.Property, op.name, null);
|
|
10818
|
-
break;
|
|
10819
|
-
}
|
|
10820
|
-
}
|
|
10821
|
-
}
|
|
10822
|
-
function isStringLiteral(expr) {
|
|
10823
|
-
return expr instanceof LiteralExpr && typeof expr.value === 'string';
|
|
10824
|
-
}
|
|
10825
10777
|
function extractAttributeOp(view, op, elements) {
|
|
10826
10778
|
if (op.expression instanceof Interpolation) {
|
|
10827
10779
|
return;
|
|
10828
10780
|
}
|
|
10829
10781
|
const ownerOp = lookupElement$2(elements, op.target);
|
|
10830
|
-
|
|
10831
|
-
if (
|
|
10832
|
-
// TemplateDefinitionBuilder
|
|
10833
|
-
|
|
10834
|
-
|
|
10835
|
-
|
|
10836
|
-
|
|
10837
|
-
|
|
10838
|
-
|
|
10839
|
-
|
|
10840
|
-
|
|
10841
|
-
|
|
10782
|
+
let extractable = op.expression.isConstant();
|
|
10783
|
+
if (view.compatibility === CompatibilityMode.TemplateDefinitionBuilder) {
|
|
10784
|
+
// TemplateDefinitionBuilder only extracted attributes that were string literals.
|
|
10785
|
+
extractable = isStringLiteral(op.expression);
|
|
10786
|
+
if (op.name === 'style' || op.name === 'class') {
|
|
10787
|
+
// For style and class attributes, TemplateDefinitionBuilder only extracted them if they were
|
|
10788
|
+
// text attributes. For example, `[attr.class]="'my-class'"` was not extracted despite being a
|
|
10789
|
+
// string literal, because it is not a text attribute.
|
|
10790
|
+
extractable &&= op.isTextAttribute;
|
|
10791
|
+
}
|
|
10792
|
+
}
|
|
10793
|
+
if (extractable) {
|
|
10794
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, op.isTemplate ? BindingKind.Template : BindingKind.Attribute, op.name, op.expression), ownerOp);
|
|
10842
10795
|
OpList.remove(op);
|
|
10843
10796
|
}
|
|
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
10797
|
}
|
|
10857
10798
|
|
|
10858
10799
|
/**
|
|
@@ -10888,7 +10829,7 @@ function phaseBindingSpecialization(job) {
|
|
|
10888
10829
|
target.nonBindable = true;
|
|
10889
10830
|
}
|
|
10890
10831
|
else {
|
|
10891
|
-
OpList.replace(op, createAttributeOp(op.target, op.name, op.expression, op.securityContext, op.isTemplate, op.sourceSpan));
|
|
10832
|
+
OpList.replace(op, createAttributeOp(op.target, op.name, op.expression, op.securityContext, op.isTextAttribute, op.isTemplate, op.sourceSpan));
|
|
10892
10833
|
}
|
|
10893
10834
|
break;
|
|
10894
10835
|
case BindingKind.Property:
|
|
@@ -10997,30 +10938,142 @@ function chainOperationsInList(opList) {
|
|
|
10997
10938
|
}
|
|
10998
10939
|
}
|
|
10999
10940
|
|
|
10941
|
+
var TagContentType;
|
|
10942
|
+
(function (TagContentType) {
|
|
10943
|
+
TagContentType[TagContentType["RAW_TEXT"] = 0] = "RAW_TEXT";
|
|
10944
|
+
TagContentType[TagContentType["ESCAPABLE_RAW_TEXT"] = 1] = "ESCAPABLE_RAW_TEXT";
|
|
10945
|
+
TagContentType[TagContentType["PARSABLE_DATA"] = 2] = "PARSABLE_DATA";
|
|
10946
|
+
})(TagContentType || (TagContentType = {}));
|
|
10947
|
+
function splitNsName(elementName) {
|
|
10948
|
+
if (elementName[0] != ':') {
|
|
10949
|
+
return [null, elementName];
|
|
10950
|
+
}
|
|
10951
|
+
const colonIndex = elementName.indexOf(':', 1);
|
|
10952
|
+
if (colonIndex === -1) {
|
|
10953
|
+
throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
|
|
10954
|
+
}
|
|
10955
|
+
return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
|
|
10956
|
+
}
|
|
10957
|
+
// `<ng-container>` tags work the same regardless the namespace
|
|
10958
|
+
function isNgContainer(tagName) {
|
|
10959
|
+
return splitNsName(tagName)[1] === 'ng-container';
|
|
10960
|
+
}
|
|
10961
|
+
// `<ng-content>` tags work the same regardless the namespace
|
|
10962
|
+
function isNgContent(tagName) {
|
|
10963
|
+
return splitNsName(tagName)[1] === 'ng-content';
|
|
10964
|
+
}
|
|
10965
|
+
// `<ng-template>` tags work the same regardless the namespace
|
|
10966
|
+
function isNgTemplate(tagName) {
|
|
10967
|
+
return splitNsName(tagName)[1] === 'ng-template';
|
|
10968
|
+
}
|
|
10969
|
+
function getNsPrefix(fullName) {
|
|
10970
|
+
return fullName === null ? null : splitNsName(fullName)[0];
|
|
10971
|
+
}
|
|
10972
|
+
function mergeNsAndName(prefix, localName) {
|
|
10973
|
+
return prefix ? `:${prefix}:${localName}` : localName;
|
|
10974
|
+
}
|
|
10975
|
+
|
|
11000
10976
|
/**
|
|
11001
10977
|
* Converts the semantic attributes of element-like operations (elements, templates) into constant
|
|
11002
10978
|
* array expressions, and lifts them into the overall component `consts`.
|
|
11003
10979
|
*/
|
|
11004
10980
|
function phaseConstCollection(cpl) {
|
|
10981
|
+
// Collect all extracted attributes.
|
|
10982
|
+
const elementAttributes = new Map();
|
|
11005
10983
|
for (const [_, view] of cpl.views) {
|
|
11006
10984
|
for (const op of view.create) {
|
|
11007
|
-
if (op.kind
|
|
11008
|
-
op.
|
|
11009
|
-
|
|
11010
|
-
|
|
11011
|
-
|
|
11012
|
-
continue;
|
|
10985
|
+
if (op.kind === OpKind.ExtractedAttribute) {
|
|
10986
|
+
const attributes = elementAttributes.get(op.target) || new ElementAttributes();
|
|
10987
|
+
elementAttributes.set(op.target, attributes);
|
|
10988
|
+
attributes.add(op.bindingKind, op.name, op.expression);
|
|
10989
|
+
OpList.remove(op);
|
|
11013
10990
|
}
|
|
11014
|
-
|
|
11015
|
-
|
|
11016
|
-
|
|
10991
|
+
}
|
|
10992
|
+
}
|
|
10993
|
+
// Serialize the extracted attributes into the const array.
|
|
10994
|
+
for (const [_, view] of cpl.views) {
|
|
10995
|
+
for (const op of view.create) {
|
|
10996
|
+
if (op.kind === OpKind.Element || op.kind === OpKind.ElementStart ||
|
|
10997
|
+
op.kind === OpKind.Template) {
|
|
10998
|
+
const attributes = elementAttributes.get(op.xref);
|
|
10999
|
+
if (attributes !== undefined) {
|
|
11000
|
+
const attrArray = serializeAttributes(attributes);
|
|
11001
|
+
if (attrArray.entries.length > 0) {
|
|
11002
|
+
op.attributes = cpl.addConst(attrArray);
|
|
11003
|
+
}
|
|
11004
|
+
}
|
|
11017
11005
|
}
|
|
11018
|
-
|
|
11019
|
-
|
|
11006
|
+
}
|
|
11007
|
+
}
|
|
11008
|
+
}
|
|
11009
|
+
/**
|
|
11010
|
+
* Shared instance of an empty array to avoid unnecessary array allocations.
|
|
11011
|
+
*/
|
|
11012
|
+
const FLYWEIGHT_ARRAY = Object.freeze([]);
|
|
11013
|
+
/**
|
|
11014
|
+
* Container for all of the various kinds of attributes which are applied on an element.
|
|
11015
|
+
*/
|
|
11016
|
+
class ElementAttributes {
|
|
11017
|
+
constructor() {
|
|
11018
|
+
this.known = new Set();
|
|
11019
|
+
this.byKind = new Map;
|
|
11020
|
+
this.projectAs = null;
|
|
11021
|
+
}
|
|
11022
|
+
get attributes() {
|
|
11023
|
+
return this.byKind.get(BindingKind.Attribute) ?? FLYWEIGHT_ARRAY;
|
|
11024
|
+
}
|
|
11025
|
+
get classes() {
|
|
11026
|
+
return this.byKind.get(BindingKind.ClassName) ?? FLYWEIGHT_ARRAY;
|
|
11027
|
+
}
|
|
11028
|
+
get styles() {
|
|
11029
|
+
return this.byKind.get(BindingKind.StyleProperty) ?? FLYWEIGHT_ARRAY;
|
|
11030
|
+
}
|
|
11031
|
+
get bindings() {
|
|
11032
|
+
return this.byKind.get(BindingKind.Property) ?? FLYWEIGHT_ARRAY;
|
|
11033
|
+
}
|
|
11034
|
+
get template() {
|
|
11035
|
+
return this.byKind.get(BindingKind.Template) ?? FLYWEIGHT_ARRAY;
|
|
11036
|
+
}
|
|
11037
|
+
get i18n() {
|
|
11038
|
+
return this.byKind.get(BindingKind.I18n) ?? FLYWEIGHT_ARRAY;
|
|
11039
|
+
}
|
|
11040
|
+
add(kind, name, value) {
|
|
11041
|
+
if (this.known.has(name)) {
|
|
11042
|
+
return;
|
|
11043
|
+
}
|
|
11044
|
+
this.known.add(name);
|
|
11045
|
+
const array = this.arrayFor(kind);
|
|
11046
|
+
array.push(...getAttributeNameLiterals$1(name));
|
|
11047
|
+
if (kind === BindingKind.Attribute || kind === BindingKind.StyleProperty) {
|
|
11048
|
+
if (value === null) {
|
|
11049
|
+
throw Error('Attribute & style element attributes must have a value');
|
|
11020
11050
|
}
|
|
11051
|
+
array.push(value);
|
|
11052
|
+
}
|
|
11053
|
+
}
|
|
11054
|
+
arrayFor(kind) {
|
|
11055
|
+
if (!this.byKind.has(kind)) {
|
|
11056
|
+
this.byKind.set(kind, []);
|
|
11021
11057
|
}
|
|
11058
|
+
return this.byKind.get(kind);
|
|
11059
|
+
}
|
|
11060
|
+
}
|
|
11061
|
+
/**
|
|
11062
|
+
* Gets an array of literal expressions representing the attribute's namespaced name.
|
|
11063
|
+
*/
|
|
11064
|
+
function getAttributeNameLiterals$1(name) {
|
|
11065
|
+
const [attributeNamespace, attributeName] = splitNsName(name);
|
|
11066
|
+
const nameLiteral = literal(attributeName);
|
|
11067
|
+
if (attributeNamespace) {
|
|
11068
|
+
return [
|
|
11069
|
+
literal(0 /* core.AttributeMarker.NamespaceURI */), literal(attributeNamespace), nameLiteral
|
|
11070
|
+
];
|
|
11022
11071
|
}
|
|
11072
|
+
return [nameLiteral];
|
|
11023
11073
|
}
|
|
11074
|
+
/**
|
|
11075
|
+
* Serializes an ElementAttributes object into an array expression.
|
|
11076
|
+
*/
|
|
11024
11077
|
function serializeAttributes({ attributes, bindings, classes, i18n, projectAs, styles, template }) {
|
|
11025
11078
|
const attrArray = [...attributes];
|
|
11026
11079
|
if (projectAs !== null) {
|
|
@@ -11426,7 +11479,7 @@ function phaseHostStylePropertyParsing(job) {
|
|
|
11426
11479
|
op.bindingKind = BindingKind.StyleProperty;
|
|
11427
11480
|
op.name = op.name.substring(STYLE_DOT.length);
|
|
11428
11481
|
if (isCssCustomProperty$1(op.name)) {
|
|
11429
|
-
op.name = hyphenate(op.name);
|
|
11482
|
+
op.name = hyphenate$1(op.name);
|
|
11430
11483
|
}
|
|
11431
11484
|
const { property, suffix } = parseProperty$1(op.name);
|
|
11432
11485
|
op.name = property;
|
|
@@ -11449,7 +11502,7 @@ function phaseHostStylePropertyParsing(job) {
|
|
|
11449
11502
|
function isCssCustomProperty$1(name) {
|
|
11450
11503
|
return name.startsWith('--');
|
|
11451
11504
|
}
|
|
11452
|
-
function hyphenate(value) {
|
|
11505
|
+
function hyphenate$1(value) {
|
|
11453
11506
|
return value
|
|
11454
11507
|
.replace(/[a-z][A-Z]/g, v => {
|
|
11455
11508
|
return v.charAt(0) + '-' + v.charAt(1);
|
|
@@ -11524,6 +11577,85 @@ function phaseNamespace(job) {
|
|
|
11524
11577
|
}
|
|
11525
11578
|
}
|
|
11526
11579
|
|
|
11580
|
+
/**
|
|
11581
|
+
* Parses string representation of a style and converts it into object literal.
|
|
11582
|
+
*
|
|
11583
|
+
* @param value string representation of style as used in the `style` attribute in HTML.
|
|
11584
|
+
* Example: `color: red; height: auto`.
|
|
11585
|
+
* @returns An array of style property name and value pairs, e.g. `['color', 'red', 'height',
|
|
11586
|
+
* 'auto']`
|
|
11587
|
+
*/
|
|
11588
|
+
function parse(value) {
|
|
11589
|
+
// we use a string array here instead of a string map
|
|
11590
|
+
// because a string-map is not guaranteed to retain the
|
|
11591
|
+
// order of the entries whereas a string array can be
|
|
11592
|
+
// constructed in a [key, value, key, value] format.
|
|
11593
|
+
const styles = [];
|
|
11594
|
+
let i = 0;
|
|
11595
|
+
let parenDepth = 0;
|
|
11596
|
+
let quote = 0 /* Char.QuoteNone */;
|
|
11597
|
+
let valueStart = 0;
|
|
11598
|
+
let propStart = 0;
|
|
11599
|
+
let currentProp = null;
|
|
11600
|
+
while (i < value.length) {
|
|
11601
|
+
const token = value.charCodeAt(i++);
|
|
11602
|
+
switch (token) {
|
|
11603
|
+
case 40 /* Char.OpenParen */:
|
|
11604
|
+
parenDepth++;
|
|
11605
|
+
break;
|
|
11606
|
+
case 41 /* Char.CloseParen */:
|
|
11607
|
+
parenDepth--;
|
|
11608
|
+
break;
|
|
11609
|
+
case 39 /* Char.QuoteSingle */:
|
|
11610
|
+
// valueStart needs to be there since prop values don't
|
|
11611
|
+
// have quotes in CSS
|
|
11612
|
+
if (quote === 0 /* Char.QuoteNone */) {
|
|
11613
|
+
quote = 39 /* Char.QuoteSingle */;
|
|
11614
|
+
}
|
|
11615
|
+
else if (quote === 39 /* Char.QuoteSingle */ && value.charCodeAt(i - 1) !== 92 /* Char.BackSlash */) {
|
|
11616
|
+
quote = 0 /* Char.QuoteNone */;
|
|
11617
|
+
}
|
|
11618
|
+
break;
|
|
11619
|
+
case 34 /* Char.QuoteDouble */:
|
|
11620
|
+
// same logic as above
|
|
11621
|
+
if (quote === 0 /* Char.QuoteNone */) {
|
|
11622
|
+
quote = 34 /* Char.QuoteDouble */;
|
|
11623
|
+
}
|
|
11624
|
+
else if (quote === 34 /* Char.QuoteDouble */ && value.charCodeAt(i - 1) !== 92 /* Char.BackSlash */) {
|
|
11625
|
+
quote = 0 /* Char.QuoteNone */;
|
|
11626
|
+
}
|
|
11627
|
+
break;
|
|
11628
|
+
case 58 /* Char.Colon */:
|
|
11629
|
+
if (!currentProp && parenDepth === 0 && quote === 0 /* Char.QuoteNone */) {
|
|
11630
|
+
currentProp = hyphenate(value.substring(propStart, i - 1).trim());
|
|
11631
|
+
valueStart = i;
|
|
11632
|
+
}
|
|
11633
|
+
break;
|
|
11634
|
+
case 59 /* Char.Semicolon */:
|
|
11635
|
+
if (currentProp && valueStart > 0 && parenDepth === 0 && quote === 0 /* Char.QuoteNone */) {
|
|
11636
|
+
const styleVal = value.substring(valueStart, i - 1).trim();
|
|
11637
|
+
styles.push(currentProp, styleVal);
|
|
11638
|
+
propStart = i;
|
|
11639
|
+
valueStart = 0;
|
|
11640
|
+
currentProp = null;
|
|
11641
|
+
}
|
|
11642
|
+
break;
|
|
11643
|
+
}
|
|
11644
|
+
}
|
|
11645
|
+
if (currentProp && valueStart) {
|
|
11646
|
+
const styleVal = value.slice(valueStart).trim();
|
|
11647
|
+
styles.push(currentProp, styleVal);
|
|
11648
|
+
}
|
|
11649
|
+
return styles;
|
|
11650
|
+
}
|
|
11651
|
+
function hyphenate(value) {
|
|
11652
|
+
return value
|
|
11653
|
+
.replace(/[a-z][A-Z]/g, v => {
|
|
11654
|
+
return v.charAt(0) + '-' + v.charAt(1);
|
|
11655
|
+
})
|
|
11656
|
+
.toLowerCase();
|
|
11657
|
+
}
|
|
11658
|
+
|
|
11527
11659
|
const BINARY_OPERATORS = new Map([
|
|
11528
11660
|
['&&', BinaryOperator.And],
|
|
11529
11661
|
['>', BinaryOperator.Bigger],
|
|
@@ -11664,7 +11796,7 @@ function getVariableName(variable, state) {
|
|
|
11664
11796
|
* Normalizes a style prop name by hyphenating it (unless its a CSS variable).
|
|
11665
11797
|
*/
|
|
11666
11798
|
function normalizeStylePropName(name) {
|
|
11667
|
-
return name.startsWith('--') ? name : hyphenate
|
|
11799
|
+
return name.startsWith('--') ? name : hyphenate(name);
|
|
11668
11800
|
}
|
|
11669
11801
|
/**
|
|
11670
11802
|
* Strips `!important` out of the given style or class name.
|
|
@@ -11846,6 +11978,34 @@ function phaseNullishCoalescing(job) {
|
|
|
11846
11978
|
}
|
|
11847
11979
|
}
|
|
11848
11980
|
|
|
11981
|
+
/**
|
|
11982
|
+
* Parses extracted style and class attributes into separate ExtractedAttributeOps per style or
|
|
11983
|
+
* class property.
|
|
11984
|
+
*/
|
|
11985
|
+
function phaseParseExtractedStyles(cpl) {
|
|
11986
|
+
for (const [_, view] of cpl.views) {
|
|
11987
|
+
for (const op of view.create) {
|
|
11988
|
+
if (op.kind === OpKind.ExtractedAttribute && op.bindingKind === BindingKind.Attribute &&
|
|
11989
|
+
isStringLiteral(op.expression)) {
|
|
11990
|
+
if (op.name === 'style') {
|
|
11991
|
+
const parsedStyles = parse(op.expression.value);
|
|
11992
|
+
for (let i = 0; i < parsedStyles.length - 1; i += 2) {
|
|
11993
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.StyleProperty, parsedStyles[i], literal(parsedStyles[i + 1])), op);
|
|
11994
|
+
}
|
|
11995
|
+
OpList.remove(op);
|
|
11996
|
+
}
|
|
11997
|
+
else if (op.name === 'class') {
|
|
11998
|
+
const parsedClasses = op.expression.value.trim().split(/\s+/g);
|
|
11999
|
+
for (const parsedClass of parsedClasses) {
|
|
12000
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.ClassName, parsedClass, null), op);
|
|
12001
|
+
}
|
|
12002
|
+
OpList.remove(op);
|
|
12003
|
+
}
|
|
12004
|
+
}
|
|
12005
|
+
}
|
|
12006
|
+
}
|
|
12007
|
+
}
|
|
12008
|
+
|
|
11849
12009
|
function phasePipeCreation(cpl) {
|
|
11850
12010
|
for (const view of cpl.views.values()) {
|
|
11851
12011
|
processPipeBindingsInView(view);
|
|
@@ -13593,6 +13753,7 @@ function transformTemplate(job) {
|
|
|
13593
13753
|
phaseStyleBindingSpecialization(job);
|
|
13594
13754
|
phaseBindingSpecialization(job);
|
|
13595
13755
|
phaseAttributeExtraction(job);
|
|
13756
|
+
phaseParseExtractedStyles(job);
|
|
13596
13757
|
phaseRemoveEmptyBindings(job);
|
|
13597
13758
|
phaseNoListenersOnTemplates(job);
|
|
13598
13759
|
phasePipeCreation(job);
|
|
@@ -13760,7 +13921,7 @@ function ingestComponent(componentName, template, constantPool) {
|
|
|
13760
13921
|
function ingestHostBinding(input, bindingParser, constantPool) {
|
|
13761
13922
|
const job = new HostBindingCompilationJob(input.componentName, constantPool, compatibilityMode);
|
|
13762
13923
|
for (const property of input.properties ?? []) {
|
|
13763
|
-
ingestHostProperty(job, property);
|
|
13924
|
+
ingestHostProperty(job, property, false);
|
|
13764
13925
|
}
|
|
13765
13926
|
for (const event of input.events ?? []) {
|
|
13766
13927
|
ingestHostEvent(job, event);
|
|
@@ -13769,7 +13930,7 @@ function ingestHostBinding(input, bindingParser, constantPool) {
|
|
|
13769
13930
|
}
|
|
13770
13931
|
// TODO: We should refactor the parser to use the same types and structures for host bindings as
|
|
13771
13932
|
// with ordinary components. This would allow us to share a lot more ingestion code.
|
|
13772
|
-
function ingestHostProperty(job, property) {
|
|
13933
|
+
function ingestHostProperty(job, property, isTextAttribute) {
|
|
13773
13934
|
let expression;
|
|
13774
13935
|
const ast = property.expression.ast;
|
|
13775
13936
|
if (ast instanceof Interpolation$1) {
|
|
@@ -13786,7 +13947,7 @@ function ingestHostProperty(job, property) {
|
|
|
13786
13947
|
bindingKind = BindingKind.Attribute;
|
|
13787
13948
|
}
|
|
13788
13949
|
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));
|
|
13950
|
+
.NONE /* TODO: what should we pass as security context? Passing NONE for now. */, isTextAttribute, false, property.sourceSpan));
|
|
13790
13951
|
}
|
|
13791
13952
|
function ingestHostEvent(job, event) { }
|
|
13792
13953
|
/**
|
|
@@ -13964,10 +14125,10 @@ function ingestBindings(view, op, element) {
|
|
|
13964
14125
|
if (element instanceof Template) {
|
|
13965
14126
|
for (const attr of element.templateAttrs) {
|
|
13966
14127
|
if (attr instanceof TextAttribute) {
|
|
13967
|
-
ingestBinding(view, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, true);
|
|
14128
|
+
ingestBinding(view, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, true, true);
|
|
13968
14129
|
}
|
|
13969
14130
|
else {
|
|
13970
|
-
ingestBinding(view, op.xref, attr.name, attr.value, attr.type, attr.unit, attr.securityContext, attr.sourceSpan, true);
|
|
14131
|
+
ingestBinding(view, op.xref, attr.name, attr.value, attr.type, attr.unit, attr.securityContext, attr.sourceSpan, false, true);
|
|
13971
14132
|
}
|
|
13972
14133
|
}
|
|
13973
14134
|
}
|
|
@@ -13975,10 +14136,10 @@ function ingestBindings(view, op, element) {
|
|
|
13975
14136
|
// This is only attribute TextLiteral bindings, such as `attr.foo="bar"`. This can never be
|
|
13976
14137
|
// `[attr.foo]="bar"` or `attr.foo="{{bar}}"`, both of which will be handled as inputs with
|
|
13977
14138
|
// `BindingType.Attribute`.
|
|
13978
|
-
ingestBinding(view, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, false);
|
|
14139
|
+
ingestBinding(view, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, true, false);
|
|
13979
14140
|
}
|
|
13980
14141
|
for (const input of element.inputs) {
|
|
13981
|
-
ingestBinding(view, op.xref, input.name, input.value, input.type, input.unit, input.securityContext, input.sourceSpan, false);
|
|
14142
|
+
ingestBinding(view, op.xref, input.name, input.value, input.type, input.unit, input.securityContext, input.sourceSpan, false, false);
|
|
13982
14143
|
}
|
|
13983
14144
|
for (const output of element.outputs) {
|
|
13984
14145
|
let listenerOp;
|
|
@@ -14024,7 +14185,7 @@ const BINDING_KINDS = new Map([
|
|
|
14024
14185
|
[3 /* e.BindingType.Style */, BindingKind.StyleProperty],
|
|
14025
14186
|
[4 /* e.BindingType.Animation */, BindingKind.Animation],
|
|
14026
14187
|
]);
|
|
14027
|
-
function ingestBinding(view, xref, name, value, type, unit, securityContext, sourceSpan, isTemplateBinding) {
|
|
14188
|
+
function ingestBinding(view, xref, name, value, type, unit, securityContext, sourceSpan, isTextAttribute, isTemplateBinding) {
|
|
14028
14189
|
if (value instanceof ASTWithSource) {
|
|
14029
14190
|
value = value.ast;
|
|
14030
14191
|
}
|
|
@@ -14039,7 +14200,7 @@ function ingestBinding(view, xref, name, value, type, unit, securityContext, sou
|
|
|
14039
14200
|
expression = value;
|
|
14040
14201
|
}
|
|
14041
14202
|
const kind = BINDING_KINDS.get(type);
|
|
14042
|
-
view.update.push(createBindingOp(xref, kind, name, expression, unit, securityContext, isTemplateBinding, sourceSpan));
|
|
14203
|
+
view.update.push(createBindingOp(xref, kind, name, expression, unit, securityContext, isTextAttribute, isTemplateBinding, sourceSpan));
|
|
14043
14204
|
}
|
|
14044
14205
|
/**
|
|
14045
14206
|
* Process all of the local references on an element-like structure in the template AST and
|
|
@@ -14234,7 +14395,7 @@ class StylingBuilder {
|
|
|
14234
14395
|
// CSS custom properties are case-sensitive so we shouldn't normalize them.
|
|
14235
14396
|
// See: https://www.w3.org/TR/css-variables-1/#defining-variables
|
|
14236
14397
|
if (!isCssCustomProperty(name)) {
|
|
14237
|
-
name = hyphenate
|
|
14398
|
+
name = hyphenate(name);
|
|
14238
14399
|
}
|
|
14239
14400
|
const { property, hasOverrideFlag, suffix: bindingSuffix } = parseProperty(name);
|
|
14240
14401
|
suffix = typeof suffix === 'string' && suffix.length !== 0 ? suffix : bindingSuffix;
|
|
@@ -21301,6 +21462,285 @@ function normalizeNgContentSelect(selectAttr) {
|
|
|
21301
21462
|
return selectAttr;
|
|
21302
21463
|
}
|
|
21303
21464
|
|
|
21465
|
+
/** Pattern for the expression in a for loop block. */
|
|
21466
|
+
const FOR_LOOP_EXPRESSION_PATTERN = /^\s*([0-9A-Za-z_$]*)\s+of\s+(.*)/;
|
|
21467
|
+
/** Pattern for the tracking expression in a for loop block. */
|
|
21468
|
+
const FOR_LOOP_TRACK_PATTERN = /^track\s+(.*)/;
|
|
21469
|
+
/** Pattern for the `as` expression in a conditional block. */
|
|
21470
|
+
const CONDITIONAL_ALIAS_PATTERN = /^as\s+(.*)/;
|
|
21471
|
+
/** Pattern used to identify an `else if` block. */
|
|
21472
|
+
const ELSE_IF_PATTERN = /^if\s/;
|
|
21473
|
+
/** Creates an `if` loop block from an HTML AST node. */
|
|
21474
|
+
function createIfBlock(ast, visitor, bindingParser) {
|
|
21475
|
+
const errors = validateIfBlock(ast);
|
|
21476
|
+
const branches = [];
|
|
21477
|
+
if (errors.length > 0) {
|
|
21478
|
+
return { node: null, errors };
|
|
21479
|
+
}
|
|
21480
|
+
// Assumes that the structure is valid since we validated it above.
|
|
21481
|
+
for (const block of ast.blocks) {
|
|
21482
|
+
const children = visitAll(visitor, block.children);
|
|
21483
|
+
// `{:else}` block.
|
|
21484
|
+
if (block.name === 'else' && block.parameters.length === 0) {
|
|
21485
|
+
branches.push(new IfBlockBranch(null, children, null, block.sourceSpan, block.startSourceSpan));
|
|
21486
|
+
continue;
|
|
21487
|
+
}
|
|
21488
|
+
// Expressions for `{:else if}` blocks start at 2 to skip the `if` from the expression.
|
|
21489
|
+
const expressionStart = block.name === 'if' ? 0 : 2;
|
|
21490
|
+
const params = parseConditionalBlockParameters(block, errors, bindingParser, expressionStart);
|
|
21491
|
+
if (params !== null) {
|
|
21492
|
+
branches.push(new IfBlockBranch(params.expression, children, params.expressionAlias, block.sourceSpan, block.startSourceSpan));
|
|
21493
|
+
}
|
|
21494
|
+
}
|
|
21495
|
+
return {
|
|
21496
|
+
node: new IfBlock(branches, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan),
|
|
21497
|
+
errors,
|
|
21498
|
+
};
|
|
21499
|
+
}
|
|
21500
|
+
/** Creates a `for` loop block from an HTML AST node. */
|
|
21501
|
+
function createForLoop(ast, visitor, bindingParser) {
|
|
21502
|
+
const [primaryBlock, ...secondaryBlocks] = ast.blocks;
|
|
21503
|
+
const errors = [];
|
|
21504
|
+
const params = parseForLoopParameters(primaryBlock, errors, bindingParser);
|
|
21505
|
+
let node = null;
|
|
21506
|
+
let empty = null;
|
|
21507
|
+
for (const block of secondaryBlocks) {
|
|
21508
|
+
if (block.name === 'empty') {
|
|
21509
|
+
if (empty !== null) {
|
|
21510
|
+
errors.push(new ParseError(block.sourceSpan, 'For loop can only have one "empty" block'));
|
|
21511
|
+
}
|
|
21512
|
+
else if (block.parameters.length > 0) {
|
|
21513
|
+
errors.push(new ParseError(block.sourceSpan, 'Empty block cannot have parameters'));
|
|
21514
|
+
}
|
|
21515
|
+
else {
|
|
21516
|
+
empty = new ForLoopBlockEmpty(visitAll(visitor, block.children), block.sourceSpan, block.startSourceSpan);
|
|
21517
|
+
}
|
|
21518
|
+
}
|
|
21519
|
+
else {
|
|
21520
|
+
errors.push(new ParseError(block.sourceSpan, `Unrecognized loop block "${block.name}"`));
|
|
21521
|
+
}
|
|
21522
|
+
}
|
|
21523
|
+
if (params !== null) {
|
|
21524
|
+
if (params.trackBy === null) {
|
|
21525
|
+
errors.push(new ParseError(ast.sourceSpan, 'For loop must have a "track" expression'));
|
|
21526
|
+
}
|
|
21527
|
+
else {
|
|
21528
|
+
node = new ForLoopBlock(params.itemName, params.expression, params.trackBy, visitAll(visitor, primaryBlock.children), empty, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
21529
|
+
}
|
|
21530
|
+
}
|
|
21531
|
+
return { node, errors };
|
|
21532
|
+
}
|
|
21533
|
+
/** Creates a switch block from an HTML AST node. */
|
|
21534
|
+
function createSwitchBlock(ast, visitor, bindingParser) {
|
|
21535
|
+
const [primaryBlock, ...secondaryBlocks] = ast.blocks;
|
|
21536
|
+
const errors = validateSwitchBlock(ast);
|
|
21537
|
+
if (errors.length > 0) {
|
|
21538
|
+
return { node: null, errors };
|
|
21539
|
+
}
|
|
21540
|
+
const primaryExpression = parseBlockParameterToBinding(primaryBlock.parameters[0], bindingParser);
|
|
21541
|
+
const cases = [];
|
|
21542
|
+
let defaultCase = null;
|
|
21543
|
+
// Here we assume that all the blocks are valid given that we validated them above.
|
|
21544
|
+
for (const block of secondaryBlocks) {
|
|
21545
|
+
const expression = block.name === 'case' ?
|
|
21546
|
+
parseBlockParameterToBinding(block.parameters[0], bindingParser) :
|
|
21547
|
+
null;
|
|
21548
|
+
const ast = new SwitchBlockCase(expression, visitAll(visitor, block.children), block.sourceSpan, block.startSourceSpan);
|
|
21549
|
+
if (expression === null) {
|
|
21550
|
+
defaultCase = ast;
|
|
21551
|
+
}
|
|
21552
|
+
else {
|
|
21553
|
+
cases.push(ast);
|
|
21554
|
+
}
|
|
21555
|
+
}
|
|
21556
|
+
// Ensure that the default case is last in the array.
|
|
21557
|
+
if (defaultCase !== null) {
|
|
21558
|
+
cases.push(defaultCase);
|
|
21559
|
+
}
|
|
21560
|
+
return {
|
|
21561
|
+
node: new SwitchBlock(primaryExpression, cases, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan),
|
|
21562
|
+
errors
|
|
21563
|
+
};
|
|
21564
|
+
}
|
|
21565
|
+
/** Parses the parameters of a `for` loop block. */
|
|
21566
|
+
function parseForLoopParameters(block, errors, bindingParser) {
|
|
21567
|
+
if (block.parameters.length === 0) {
|
|
21568
|
+
errors.push(new ParseError(block.sourceSpan, 'For loop does not have an expression'));
|
|
21569
|
+
return null;
|
|
21570
|
+
}
|
|
21571
|
+
const [expressionParam, ...secondaryParams] = block.parameters;
|
|
21572
|
+
const match = stripOptionalParentheses(expressionParam, errors)?.match(FOR_LOOP_EXPRESSION_PATTERN);
|
|
21573
|
+
if (!match || match[2].trim().length === 0) {
|
|
21574
|
+
errors.push(new ParseError(expressionParam.sourceSpan, 'Cannot parse expression. For loop expression must match the pattern "<identifier> of <expression>"'));
|
|
21575
|
+
return null;
|
|
21576
|
+
}
|
|
21577
|
+
const [, itemName, rawExpression] = match;
|
|
21578
|
+
const result = {
|
|
21579
|
+
itemName,
|
|
21580
|
+
trackBy: null,
|
|
21581
|
+
expression: bindingParser.parseBinding(rawExpression, false, expressionParam.sourceSpan,
|
|
21582
|
+
// Note: `lastIndexOf` here should be enough to know the start index of the expression,
|
|
21583
|
+
// because we know that it'll be the last matching group. Ideally we could use the `d`
|
|
21584
|
+
// flag on the regex and get the index from `match.indices`, but it's unclear if we can
|
|
21585
|
+
// use it yet since it's a relatively new feature. See:
|
|
21586
|
+
// https://github.com/tc39/proposal-regexp-match-indices
|
|
21587
|
+
Math.max(0, expressionParam.expression.lastIndexOf(rawExpression)))
|
|
21588
|
+
};
|
|
21589
|
+
for (const param of secondaryParams) {
|
|
21590
|
+
const trackMatch = param.expression.match(FOR_LOOP_TRACK_PATTERN);
|
|
21591
|
+
// For now loops can only have a `track` parameter.
|
|
21592
|
+
// We may want to rework this later if we add more.
|
|
21593
|
+
if (trackMatch === null) {
|
|
21594
|
+
errors.push(new ParseError(param.sourceSpan, `Unrecognized loop paramater "${param.expression}"`));
|
|
21595
|
+
}
|
|
21596
|
+
else if (result.trackBy !== null) {
|
|
21597
|
+
errors.push(new ParseError(param.sourceSpan, 'For loop can only have one "track" expression'));
|
|
21598
|
+
}
|
|
21599
|
+
else {
|
|
21600
|
+
result.trackBy = trackMatch[1].trim();
|
|
21601
|
+
}
|
|
21602
|
+
}
|
|
21603
|
+
return result;
|
|
21604
|
+
}
|
|
21605
|
+
/** Checks that the shape of a `if` block is valid. Returns an array of errors. */
|
|
21606
|
+
function validateIfBlock(ast) {
|
|
21607
|
+
const errors = [];
|
|
21608
|
+
let hasElse = false;
|
|
21609
|
+
for (let i = 0; i < ast.blocks.length; i++) {
|
|
21610
|
+
const block = ast.blocks[i];
|
|
21611
|
+
// Conditional blocks only allow `if`, `else if` and `else` blocks.
|
|
21612
|
+
if ((block.name !== 'if' || i > 0) && block.name !== 'else') {
|
|
21613
|
+
errors.push(new ParseError(block.sourceSpan, `Unrecognized conditional block "${block.name}"`));
|
|
21614
|
+
continue;
|
|
21615
|
+
}
|
|
21616
|
+
if (block.name === 'if') {
|
|
21617
|
+
continue;
|
|
21618
|
+
}
|
|
21619
|
+
if (block.parameters.length === 0) {
|
|
21620
|
+
if (hasElse) {
|
|
21621
|
+
errors.push(new ParseError(block.sourceSpan, 'Conditional can only have one "else" block'));
|
|
21622
|
+
}
|
|
21623
|
+
else if (ast.blocks.length > 1 && i < ast.blocks.length - 1) {
|
|
21624
|
+
errors.push(new ParseError(block.sourceSpan, 'Else block must be last inside the conditional'));
|
|
21625
|
+
}
|
|
21626
|
+
hasElse = true;
|
|
21627
|
+
// `else if` is an edge case, because it has a space after the block name
|
|
21628
|
+
// which means that the `if` is captured as a part of the parameters.
|
|
21629
|
+
}
|
|
21630
|
+
else if (block.parameters.length > 0 && !ELSE_IF_PATTERN.test(block.parameters[0].expression)) {
|
|
21631
|
+
errors.push(new ParseError(block.sourceSpan, 'Else block cannot have parameters'));
|
|
21632
|
+
}
|
|
21633
|
+
}
|
|
21634
|
+
return errors;
|
|
21635
|
+
}
|
|
21636
|
+
/** Checks that the shape of a `switch` block is valid. Returns an array of errors. */
|
|
21637
|
+
function validateSwitchBlock(ast) {
|
|
21638
|
+
const [primaryBlock, ...secondaryBlocks] = ast.blocks;
|
|
21639
|
+
const errors = [];
|
|
21640
|
+
let hasDefault = false;
|
|
21641
|
+
if (primaryBlock.children.length > 0) {
|
|
21642
|
+
errors.push(new ParseError(primaryBlock.sourceSpan, 'Switch block can only contain "case" and "default" blocks'));
|
|
21643
|
+
}
|
|
21644
|
+
if (primaryBlock.parameters.length !== 1) {
|
|
21645
|
+
errors.push(new ParseError(primaryBlock.sourceSpan, 'Switch block must have exactly one parameter'));
|
|
21646
|
+
}
|
|
21647
|
+
for (const block of secondaryBlocks) {
|
|
21648
|
+
if (block.name === 'case') {
|
|
21649
|
+
if (block.parameters.length !== 1) {
|
|
21650
|
+
errors.push(new ParseError(block.sourceSpan, 'Case block must have exactly one parameter'));
|
|
21651
|
+
}
|
|
21652
|
+
}
|
|
21653
|
+
else if (block.name === 'default') {
|
|
21654
|
+
if (hasDefault) {
|
|
21655
|
+
errors.push(new ParseError(block.sourceSpan, 'Switch block can only have one "default" block'));
|
|
21656
|
+
}
|
|
21657
|
+
else if (block.parameters.length > 0) {
|
|
21658
|
+
errors.push(new ParseError(block.sourceSpan, 'Default block cannot have parameters'));
|
|
21659
|
+
}
|
|
21660
|
+
hasDefault = true;
|
|
21661
|
+
}
|
|
21662
|
+
else {
|
|
21663
|
+
errors.push(new ParseError(block.sourceSpan, 'Switch block can only contain "case" and "default" blocks'));
|
|
21664
|
+
}
|
|
21665
|
+
}
|
|
21666
|
+
return errors;
|
|
21667
|
+
}
|
|
21668
|
+
/** Parses a block parameter into a binding AST. */
|
|
21669
|
+
function parseBlockParameterToBinding(ast, bindingParser, start = 0) {
|
|
21670
|
+
return bindingParser.parseBinding(ast.expression.slice(start), false, ast.sourceSpan, ast.sourceSpan.start.offset + start);
|
|
21671
|
+
}
|
|
21672
|
+
/** Parses the parameter of a conditional block (`if` or `else if`). */
|
|
21673
|
+
function parseConditionalBlockParameters(block, errors, bindingParser, primaryExpressionStart) {
|
|
21674
|
+
if (block.parameters.length === 0) {
|
|
21675
|
+
errors.push(new ParseError(block.sourceSpan, 'Conditional block does not have an expression'));
|
|
21676
|
+
return null;
|
|
21677
|
+
}
|
|
21678
|
+
const expression = parseBlockParameterToBinding(block.parameters[0], bindingParser, primaryExpressionStart);
|
|
21679
|
+
let expressionAlias = null;
|
|
21680
|
+
// Start from 1 since we processed the first parameter already.
|
|
21681
|
+
for (let i = 1; i < block.parameters.length; i++) {
|
|
21682
|
+
const param = block.parameters[i];
|
|
21683
|
+
const aliasMatch = param.expression.match(CONDITIONAL_ALIAS_PATTERN);
|
|
21684
|
+
// For now conditionals can only have an `as` parameter.
|
|
21685
|
+
// We may want to rework this later if we add more.
|
|
21686
|
+
if (aliasMatch === null) {
|
|
21687
|
+
errors.push(new ParseError(param.sourceSpan, `Unrecognized conditional paramater "${param.expression}"`));
|
|
21688
|
+
}
|
|
21689
|
+
else if (expressionAlias !== null) {
|
|
21690
|
+
errors.push(new ParseError(param.sourceSpan, 'Conditional can only have one "as" expression'));
|
|
21691
|
+
}
|
|
21692
|
+
else {
|
|
21693
|
+
expressionAlias = aliasMatch[1].trim();
|
|
21694
|
+
}
|
|
21695
|
+
}
|
|
21696
|
+
return { expression, expressionAlias };
|
|
21697
|
+
}
|
|
21698
|
+
/** Strips optional parentheses around from a control from expression parameter. */
|
|
21699
|
+
function stripOptionalParentheses(param, errors) {
|
|
21700
|
+
const expression = param.expression;
|
|
21701
|
+
const spaceRegex = /^\s$/;
|
|
21702
|
+
let openParens = 0;
|
|
21703
|
+
let start = 0;
|
|
21704
|
+
let end = expression.length - 1;
|
|
21705
|
+
for (let i = 0; i < expression.length; i++) {
|
|
21706
|
+
const char = expression[i];
|
|
21707
|
+
if (char === '(') {
|
|
21708
|
+
start = i + 1;
|
|
21709
|
+
openParens++;
|
|
21710
|
+
}
|
|
21711
|
+
else if (spaceRegex.test(char)) {
|
|
21712
|
+
continue;
|
|
21713
|
+
}
|
|
21714
|
+
else {
|
|
21715
|
+
break;
|
|
21716
|
+
}
|
|
21717
|
+
}
|
|
21718
|
+
if (openParens === 0) {
|
|
21719
|
+
return expression;
|
|
21720
|
+
}
|
|
21721
|
+
for (let i = expression.length - 1; i > -1; i--) {
|
|
21722
|
+
const char = expression[i];
|
|
21723
|
+
if (char === ')') {
|
|
21724
|
+
end = i;
|
|
21725
|
+
openParens--;
|
|
21726
|
+
if (openParens === 0) {
|
|
21727
|
+
break;
|
|
21728
|
+
}
|
|
21729
|
+
}
|
|
21730
|
+
else if (spaceRegex.test(char)) {
|
|
21731
|
+
continue;
|
|
21732
|
+
}
|
|
21733
|
+
else {
|
|
21734
|
+
break;
|
|
21735
|
+
}
|
|
21736
|
+
}
|
|
21737
|
+
if (openParens !== 0) {
|
|
21738
|
+
errors.push(new ParseError(param.sourceSpan, 'Unclosed parentheses in expression'));
|
|
21739
|
+
return null;
|
|
21740
|
+
}
|
|
21741
|
+
return expression.slice(start, end);
|
|
21742
|
+
}
|
|
21743
|
+
|
|
21304
21744
|
/** Pattern for a timing value in a trigger. */
|
|
21305
21745
|
const TIME_PATTERN = /^\d+(ms|s)?$/;
|
|
21306
21746
|
/** Pattern for a separator between keywords in a trigger expression. */
|
|
@@ -21322,38 +21762,41 @@ var OnTriggerType;
|
|
|
21322
21762
|
OnTriggerType["VIEWPORT"] = "viewport";
|
|
21323
21763
|
})(OnTriggerType || (OnTriggerType = {}));
|
|
21324
21764
|
/** Parses a `when` deferred trigger. */
|
|
21325
|
-
function parseWhenTrigger({ expression, sourceSpan }, bindingParser, errors) {
|
|
21765
|
+
function parseWhenTrigger({ expression, sourceSpan }, bindingParser, triggers, errors) {
|
|
21326
21766
|
const whenIndex = expression.indexOf('when');
|
|
21327
21767
|
// This is here just to be safe, we shouldn't enter this function
|
|
21328
21768
|
// in the first place if a block doesn't have the "when" keyword.
|
|
21329
21769
|
if (whenIndex === -1) {
|
|
21330
21770
|
errors.push(new ParseError(sourceSpan, `Could not find "when" keyword in expression`));
|
|
21331
|
-
return null;
|
|
21332
21771
|
}
|
|
21333
|
-
|
|
21334
|
-
|
|
21335
|
-
|
|
21772
|
+
else {
|
|
21773
|
+
const start = getTriggerParametersStart(expression, whenIndex + 1);
|
|
21774
|
+
const parsed = bindingParser.parseBinding(expression.slice(start), false, sourceSpan, sourceSpan.start.offset + start);
|
|
21775
|
+
trackTrigger('when', triggers, errors, new BoundDeferredTrigger(parsed, sourceSpan));
|
|
21776
|
+
}
|
|
21336
21777
|
}
|
|
21337
21778
|
/** Parses an `on` trigger */
|
|
21338
|
-
function parseOnTrigger({ expression, sourceSpan }, errors) {
|
|
21779
|
+
function parseOnTrigger({ expression, sourceSpan }, triggers, errors) {
|
|
21339
21780
|
const onIndex = expression.indexOf('on');
|
|
21340
21781
|
// This is here just to be safe, we shouldn't enter this function
|
|
21341
21782
|
// in the first place if a block doesn't have the "on" keyword.
|
|
21342
21783
|
if (onIndex === -1) {
|
|
21343
21784
|
errors.push(new ParseError(sourceSpan, `Could not find "on" keyword in expression`));
|
|
21344
|
-
return [];
|
|
21345
21785
|
}
|
|
21346
|
-
|
|
21347
|
-
|
|
21786
|
+
else {
|
|
21787
|
+
const start = getTriggerParametersStart(expression, onIndex + 1);
|
|
21788
|
+
const parser = new OnTriggerParser(expression, start, sourceSpan, triggers, errors);
|
|
21789
|
+
parser.parse();
|
|
21790
|
+
}
|
|
21348
21791
|
}
|
|
21349
21792
|
class OnTriggerParser {
|
|
21350
|
-
constructor(expression, start, span, errors) {
|
|
21793
|
+
constructor(expression, start, span, triggers, errors) {
|
|
21351
21794
|
this.expression = expression;
|
|
21352
21795
|
this.start = start;
|
|
21353
21796
|
this.span = span;
|
|
21797
|
+
this.triggers = triggers;
|
|
21354
21798
|
this.errors = errors;
|
|
21355
21799
|
this.index = 0;
|
|
21356
|
-
this.triggers = [];
|
|
21357
21800
|
this.tokens = new Lexer().tokenize(expression.slice(start));
|
|
21358
21801
|
}
|
|
21359
21802
|
parse() {
|
|
@@ -21384,7 +21827,6 @@ class OnTriggerParser {
|
|
|
21384
21827
|
}
|
|
21385
21828
|
this.advance();
|
|
21386
21829
|
}
|
|
21387
|
-
return this.triggers;
|
|
21388
21830
|
}
|
|
21389
21831
|
advance() {
|
|
21390
21832
|
this.index++;
|
|
@@ -21405,22 +21847,22 @@ class OnTriggerParser {
|
|
|
21405
21847
|
try {
|
|
21406
21848
|
switch (identifier.toString()) {
|
|
21407
21849
|
case OnTriggerType.IDLE:
|
|
21408
|
-
this.
|
|
21850
|
+
this.trackTrigger('idle', createIdleTrigger(parameters, sourceSpan));
|
|
21409
21851
|
break;
|
|
21410
21852
|
case OnTriggerType.TIMER:
|
|
21411
|
-
this.
|
|
21853
|
+
this.trackTrigger('timer', createTimerTrigger(parameters, sourceSpan));
|
|
21412
21854
|
break;
|
|
21413
21855
|
case OnTriggerType.INTERACTION:
|
|
21414
|
-
this.
|
|
21856
|
+
this.trackTrigger('interaction', createInteractionTrigger(parameters, sourceSpan));
|
|
21415
21857
|
break;
|
|
21416
21858
|
case OnTriggerType.IMMEDIATE:
|
|
21417
|
-
this.
|
|
21859
|
+
this.trackTrigger('immediate', createImmediateTrigger(parameters, sourceSpan));
|
|
21418
21860
|
break;
|
|
21419
21861
|
case OnTriggerType.HOVER:
|
|
21420
|
-
this.
|
|
21862
|
+
this.trackTrigger('hover', createHoverTrigger(parameters, sourceSpan));
|
|
21421
21863
|
break;
|
|
21422
21864
|
case OnTriggerType.VIEWPORT:
|
|
21423
|
-
this.
|
|
21865
|
+
this.trackTrigger('viewport', createViewportTrigger(parameters, sourceSpan));
|
|
21424
21866
|
break;
|
|
21425
21867
|
default:
|
|
21426
21868
|
throw new Error(`Unrecognized trigger type "${identifier}"`);
|
|
@@ -21489,6 +21931,9 @@ class OnTriggerParser {
|
|
|
21489
21931
|
// Eventually we could expose this information on the token directly.
|
|
21490
21932
|
return this.expression.slice(this.start + this.token().index, this.start + this.token().end);
|
|
21491
21933
|
}
|
|
21934
|
+
trackTrigger(name, trigger) {
|
|
21935
|
+
trackTrigger(name, this.triggers, this.errors, trigger);
|
|
21936
|
+
}
|
|
21492
21937
|
error(token, message) {
|
|
21493
21938
|
const newStart = this.span.start.moveBy(this.start + token.index);
|
|
21494
21939
|
const newEnd = newStart.moveBy(token.end - token.index);
|
|
@@ -21498,6 +21943,15 @@ class OnTriggerParser {
|
|
|
21498
21943
|
this.error(token, `Unexpected token "${token}"`);
|
|
21499
21944
|
}
|
|
21500
21945
|
}
|
|
21946
|
+
/** Adds a trigger to a map of triggers. */
|
|
21947
|
+
function trackTrigger(name, allTriggers, errors, trigger) {
|
|
21948
|
+
if (allTriggers[name]) {
|
|
21949
|
+
errors.push(new ParseError(trigger.sourceSpan, `Duplicate "${name}" trigger is not allowed`));
|
|
21950
|
+
}
|
|
21951
|
+
else {
|
|
21952
|
+
allTriggers[name] = trigger;
|
|
21953
|
+
}
|
|
21954
|
+
}
|
|
21501
21955
|
function createIdleTrigger(parameters, sourceSpan) {
|
|
21502
21956
|
if (parameters.length > 0) {
|
|
21503
21957
|
throw new Error(`"${OnTriggerType.IDLE}" trigger cannot have parameters`);
|
|
@@ -21641,6 +22095,9 @@ function parsePlaceholderBlock(ast, visitor) {
|
|
|
21641
22095
|
let minimumTime = null;
|
|
21642
22096
|
for (const param of ast.parameters) {
|
|
21643
22097
|
if (MINIMUM_PARAMETER_PATTERN.test(param.expression)) {
|
|
22098
|
+
if (minimumTime != null) {
|
|
22099
|
+
throw new Error(`Placeholder block can only have one "minimum" parameter`);
|
|
22100
|
+
}
|
|
21644
22101
|
const parsedTime = parseDeferredTime(param.expression.slice(getTriggerParametersStart(param.expression)));
|
|
21645
22102
|
if (parsedTime === null) {
|
|
21646
22103
|
throw new Error(`Could not parse time value of parameter "minimum"`);
|
|
@@ -21658,6 +22115,9 @@ function parseLoadingBlock(ast, visitor) {
|
|
|
21658
22115
|
let minimumTime = null;
|
|
21659
22116
|
for (const param of ast.parameters) {
|
|
21660
22117
|
if (AFTER_PARAMETER_PATTERN.test(param.expression)) {
|
|
22118
|
+
if (afterTime != null) {
|
|
22119
|
+
throw new Error(`Loading block can only have one "after" parameter`);
|
|
22120
|
+
}
|
|
21661
22121
|
const parsedTime = parseDeferredTime(param.expression.slice(getTriggerParametersStart(param.expression)));
|
|
21662
22122
|
if (parsedTime === null) {
|
|
21663
22123
|
throw new Error(`Could not parse time value of parameter "after"`);
|
|
@@ -21665,6 +22125,9 @@ function parseLoadingBlock(ast, visitor) {
|
|
|
21665
22125
|
afterTime = parsedTime;
|
|
21666
22126
|
}
|
|
21667
22127
|
else if (MINIMUM_PARAMETER_PATTERN.test(param.expression)) {
|
|
22128
|
+
if (minimumTime != null) {
|
|
22129
|
+
throw new Error(`Loading block can only have one "minimum" parameter`);
|
|
22130
|
+
}
|
|
21668
22131
|
const parsedTime = parseDeferredTime(param.expression.slice(getTriggerParametersStart(param.expression)));
|
|
21669
22132
|
if (parsedTime === null) {
|
|
21670
22133
|
throw new Error(`Could not parse time value of parameter "minimum"`);
|
|
@@ -21684,24 +22147,22 @@ function parseErrorBlock(ast, visitor) {
|
|
|
21684
22147
|
return new DeferredBlockError(visitAll(visitor, ast.children), ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
21685
22148
|
}
|
|
21686
22149
|
function parsePrimaryTriggers(params, bindingParser, errors) {
|
|
21687
|
-
const triggers =
|
|
21688
|
-
const prefetchTriggers =
|
|
22150
|
+
const triggers = {};
|
|
22151
|
+
const prefetchTriggers = {};
|
|
21689
22152
|
for (const param of params) {
|
|
21690
22153
|
// The lexer ignores the leading spaces so we can assume
|
|
21691
22154
|
// that the expression starts with a keyword.
|
|
21692
22155
|
if (WHEN_PARAMETER_PATTERN.test(param.expression)) {
|
|
21693
|
-
|
|
21694
|
-
result !== null && triggers.push(result);
|
|
22156
|
+
parseWhenTrigger(param, bindingParser, triggers, errors);
|
|
21695
22157
|
}
|
|
21696
22158
|
else if (ON_PARAMETER_PATTERN.test(param.expression)) {
|
|
21697
|
-
|
|
22159
|
+
parseOnTrigger(param, triggers, errors);
|
|
21698
22160
|
}
|
|
21699
22161
|
else if (PREFETCH_WHEN_PATTERN.test(param.expression)) {
|
|
21700
|
-
|
|
21701
|
-
result !== null && prefetchTriggers.push(result);
|
|
22162
|
+
parseWhenTrigger(param, bindingParser, prefetchTriggers, errors);
|
|
21702
22163
|
}
|
|
21703
22164
|
else if (PREFETCH_ON_PATTERN.test(param.expression)) {
|
|
21704
|
-
|
|
22165
|
+
parseOnTrigger(param, prefetchTriggers, errors);
|
|
21705
22166
|
}
|
|
21706
22167
|
else {
|
|
21707
22168
|
errors.push(new ParseError(param.sourceSpan, 'Unrecognized trigger'));
|
|
@@ -21947,13 +22408,33 @@ class HtmlAstToIvyAst {
|
|
|
21947
22408
|
this.reportError('Block group must have at least one block.', group.sourceSpan);
|
|
21948
22409
|
return null;
|
|
21949
22410
|
}
|
|
21950
|
-
if (
|
|
21951
|
-
|
|
21952
|
-
|
|
21953
|
-
return node;
|
|
22411
|
+
if (!this.options.enabledBlockTypes.has(primaryBlock.name)) {
|
|
22412
|
+
this.reportError(`Unrecognized block "${primaryBlock.name}".`, primaryBlock.sourceSpan);
|
|
22413
|
+
return null;
|
|
21954
22414
|
}
|
|
21955
|
-
|
|
21956
|
-
|
|
22415
|
+
let result = null;
|
|
22416
|
+
switch (primaryBlock.name) {
|
|
22417
|
+
case 'defer':
|
|
22418
|
+
result = createDeferredBlock(group, this, this.bindingParser);
|
|
22419
|
+
break;
|
|
22420
|
+
case 'switch':
|
|
22421
|
+
result = createSwitchBlock(group, this, this.bindingParser);
|
|
22422
|
+
break;
|
|
22423
|
+
case 'for':
|
|
22424
|
+
result = createForLoop(group, this, this.bindingParser);
|
|
22425
|
+
break;
|
|
22426
|
+
case 'if':
|
|
22427
|
+
result = createIfBlock(group, this, this.bindingParser);
|
|
22428
|
+
break;
|
|
22429
|
+
default:
|
|
22430
|
+
result = {
|
|
22431
|
+
node: null,
|
|
22432
|
+
errors: [new ParseError(primaryBlock.sourceSpan, `Unrecognized block "${primaryBlock.name}".`)]
|
|
22433
|
+
};
|
|
22434
|
+
break;
|
|
22435
|
+
}
|
|
22436
|
+
this.errors.push(...result.errors);
|
|
22437
|
+
return result.node;
|
|
21957
22438
|
}
|
|
21958
22439
|
visitBlock(block, context) { }
|
|
21959
22440
|
visitBlockParameter(parameter, context) { }
|
|
@@ -23308,6 +23789,10 @@ class TemplateDefinitionBuilder {
|
|
|
23308
23789
|
this.visitTextAttribute = invalid;
|
|
23309
23790
|
this.visitBoundAttribute = invalid;
|
|
23310
23791
|
this.visitBoundEvent = invalid;
|
|
23792
|
+
this.visitDeferredTrigger = invalid;
|
|
23793
|
+
this.visitDeferredBlockError = invalid;
|
|
23794
|
+
this.visitDeferredBlockLoading = invalid;
|
|
23795
|
+
this.visitDeferredBlockPlaceholder = invalid;
|
|
23311
23796
|
this._bindingScope = parentBindingScope.nestedScope(level);
|
|
23312
23797
|
// Turn the relative context file path into an identifier by replacing non-alphanumeric
|
|
23313
23798
|
// characters with underscores.
|
|
@@ -23864,28 +24349,22 @@ class TemplateDefinitionBuilder {
|
|
|
23864
24349
|
this.creationInstruction(span, isNgContainer$1 ? Identifiers.elementContainerEnd : Identifiers.elementEnd);
|
|
23865
24350
|
}
|
|
23866
24351
|
}
|
|
23867
|
-
|
|
23868
|
-
const NG_TEMPLATE_TAG_NAME = 'ng-template';
|
|
24352
|
+
createEmbeddedTemplateFn(tagName, children, contextNameSuffix, sourceSpan, variables = [], attrsExprs, references, i18n) {
|
|
23869
24353
|
const templateIndex = this.allocateDataSlot();
|
|
23870
|
-
if (this.i18n) {
|
|
23871
|
-
this.i18n.appendTemplate(
|
|
24354
|
+
if (this.i18n && i18n) {
|
|
24355
|
+
this.i18n.appendTemplate(i18n, templateIndex);
|
|
23872
24356
|
}
|
|
23873
|
-
const
|
|
23874
|
-
const contextName = `${this.contextName}${template.tagName ? '_' + sanitizeIdentifier(template.tagName) : ''}_${templateIndex}`;
|
|
24357
|
+
const contextName = `${this.contextName}${contextNameSuffix}_${templateIndex}`;
|
|
23875
24358
|
const templateName = `${contextName}_Template`;
|
|
23876
24359
|
const parameters = [
|
|
23877
24360
|
literal(templateIndex),
|
|
23878
24361
|
variable(templateName),
|
|
23879
|
-
|
|
23880
|
-
|
|
23881
|
-
literal(tagNameWithoutNamespace),
|
|
24362
|
+
literal(tagName),
|
|
24363
|
+
this.addAttrsToConsts(attrsExprs || null),
|
|
23882
24364
|
];
|
|
23883
|
-
// prepare attributes parameter (including attributes used for directive matching)
|
|
23884
|
-
const attrsExprs = this.getAttributeExpressions(NG_TEMPLATE_TAG_NAME, template.attributes, template.inputs, template.outputs, undefined /* styles */, template.templateAttrs);
|
|
23885
|
-
parameters.push(this.addAttrsToConsts(attrsExprs));
|
|
23886
24365
|
// local refs (ex.: <ng-template #foo>)
|
|
23887
|
-
if (
|
|
23888
|
-
const refs = this.prepareRefsArray(
|
|
24366
|
+
if (references && references.length > 0) {
|
|
24367
|
+
const refs = this.prepareRefsArray(references);
|
|
23889
24368
|
parameters.push(this.addToConsts(refs));
|
|
23890
24369
|
parameters.push(importExpr(Identifiers.templateRefExtractor));
|
|
23891
24370
|
}
|
|
@@ -23896,17 +24375,28 @@ class TemplateDefinitionBuilder {
|
|
|
23896
24375
|
// be able to support bindings in nested templates to local refs that occur after the
|
|
23897
24376
|
// template definition. e.g. <div *ngIf="showing">{{ foo }}</div> <div #foo></div>
|
|
23898
24377
|
this._nestedTemplateFns.push(() => {
|
|
23899
|
-
const templateFunctionExpr = templateVisitor.buildTemplateFunction(
|
|
24378
|
+
const templateFunctionExpr = templateVisitor.buildTemplateFunction(children, variables, this._ngContentReservedSlots.length + this._ngContentSelectorsOffset, i18n);
|
|
23900
24379
|
this.constantPool.statements.push(templateFunctionExpr.toDeclStmt(templateName));
|
|
23901
24380
|
if (templateVisitor._ngContentReservedSlots.length) {
|
|
23902
24381
|
this._ngContentReservedSlots.push(...templateVisitor._ngContentReservedSlots);
|
|
23903
24382
|
}
|
|
23904
24383
|
});
|
|
23905
24384
|
// e.g. template(1, MyComp_Template_1)
|
|
23906
|
-
this.creationInstruction(
|
|
24385
|
+
this.creationInstruction(sourceSpan, Identifiers.templateCreate, () => {
|
|
23907
24386
|
parameters.splice(2, 0, literal(templateVisitor.getConstCount()), literal(templateVisitor.getVarCount()));
|
|
23908
24387
|
return trimTrailingNulls(parameters);
|
|
23909
24388
|
});
|
|
24389
|
+
return templateIndex;
|
|
24390
|
+
}
|
|
24391
|
+
visitTemplate(template) {
|
|
24392
|
+
// We don't care about the tag's namespace here, because we infer
|
|
24393
|
+
// it based on the parent nodes inside the template instruction.
|
|
24394
|
+
const tagNameWithoutNamespace = template.tagName ? splitNsName(template.tagName)[1] : template.tagName;
|
|
24395
|
+
const contextNameSuffix = template.tagName ? '_' + sanitizeIdentifier(template.tagName) : '';
|
|
24396
|
+
const NG_TEMPLATE_TAG_NAME = 'ng-template';
|
|
24397
|
+
// prepare attributes parameter (including attributes used for directive matching)
|
|
24398
|
+
const attrsExprs = this.getAttributeExpressions(NG_TEMPLATE_TAG_NAME, template.attributes, template.inputs, template.outputs, undefined /* styles */, template.templateAttrs);
|
|
24399
|
+
const templateIndex = this.createEmbeddedTemplateFn(tagNameWithoutNamespace, template.children, contextNameSuffix, template.sourceSpan, template.variables, attrsExprs, template.references, template.i18n);
|
|
23910
24400
|
// handle property bindings e.g. ɵɵproperty('ngForOf', ctx.items), et al;
|
|
23911
24401
|
this.templatePropertyBindings(templateIndex, template.templateAttrs);
|
|
23912
24402
|
// Only add normal input/output binding instructions on explicit <ng-template> elements.
|
|
@@ -24001,49 +24491,115 @@ class TemplateDefinitionBuilder {
|
|
|
24001
24491
|
return null;
|
|
24002
24492
|
}
|
|
24003
24493
|
visitDeferredBlock(deferred) {
|
|
24004
|
-
const
|
|
24494
|
+
const { loading, placeholder, error, triggers, prefetchTriggers } = deferred;
|
|
24495
|
+
const primaryTemplateIndex = this.createEmbeddedTemplateFn(null, deferred.children, '_Defer', deferred.sourceSpan);
|
|
24496
|
+
const loadingIndex = loading ?
|
|
24497
|
+
this.createEmbeddedTemplateFn(null, loading.children, '_DeferLoading', loading.sourceSpan) :
|
|
24498
|
+
null;
|
|
24499
|
+
const loadingConsts = loading ?
|
|
24500
|
+
trimTrailingNulls([literal(loading.minimumTime), literal(loading.afterTime)]) :
|
|
24501
|
+
null;
|
|
24502
|
+
const placeholderIndex = placeholder ?
|
|
24503
|
+
this.createEmbeddedTemplateFn(null, placeholder.children, '_DeferPlaceholder', placeholder.sourceSpan) :
|
|
24504
|
+
null;
|
|
24505
|
+
const placeholderConsts = placeholder && placeholder.minimumTime !== null ?
|
|
24506
|
+
// TODO(crisbeto): potentially pass the time directly instead of storing it in the `consts`
|
|
24507
|
+
// since `{:placeholder}` can only have one parameter?
|
|
24508
|
+
literalArr([literal(placeholder.minimumTime)]) :
|
|
24509
|
+
null;
|
|
24510
|
+
const errorIndex = error ?
|
|
24511
|
+
this.createEmbeddedTemplateFn(null, error.children, '_DeferError', error.sourceSpan) :
|
|
24512
|
+
null;
|
|
24513
|
+
// Note: we generate this last so the index matches the instruction order.
|
|
24514
|
+
const deferredIndex = this.allocateDataSlot();
|
|
24515
|
+
const depsFnName = `${this.contextName}_Defer_${deferredIndex}_DepsFn`;
|
|
24516
|
+
// e.g. `defer(1, 0, MyComp_Defer_1_DepsFn, ...)`
|
|
24517
|
+
this.creationInstruction(deferred.sourceSpan, Identifiers.defer, trimTrailingNulls([
|
|
24518
|
+
literal(deferredIndex),
|
|
24519
|
+
literal(primaryTemplateIndex),
|
|
24520
|
+
this.createDeferredDepsFunction(depsFnName, deferred),
|
|
24521
|
+
literal(loadingIndex),
|
|
24522
|
+
literal(placeholderIndex),
|
|
24523
|
+
literal(errorIndex),
|
|
24524
|
+
loadingConsts?.length ? this.addToConsts(literalArr(loadingConsts)) : TYPED_NULL_EXPR,
|
|
24525
|
+
placeholderConsts ? this.addToConsts(placeholderConsts) : TYPED_NULL_EXPR,
|
|
24526
|
+
]));
|
|
24527
|
+
this.createDeferTriggerInstructions(deferredIndex, triggers, false);
|
|
24528
|
+
this.createDeferTriggerInstructions(deferredIndex, prefetchTriggers, true);
|
|
24529
|
+
}
|
|
24530
|
+
createDeferredDepsFunction(name, deferred) {
|
|
24005
24531
|
const deferredDeps = this.deferBlocks.get(deferred);
|
|
24006
|
-
|
|
24007
|
-
|
|
24008
|
-
|
|
24009
|
-
|
|
24010
|
-
|
|
24011
|
-
|
|
24012
|
-
|
|
24013
|
-
|
|
24014
|
-
|
|
24015
|
-
|
|
24016
|
-
|
|
24017
|
-
|
|
24018
|
-
|
|
24019
|
-
|
|
24020
|
-
|
|
24021
|
-
|
|
24022
|
-
dependencyExp.push(importExpr);
|
|
24023
|
-
}
|
|
24024
|
-
else {
|
|
24025
|
-
// Non-deferrable symbol, just use a reference to the type.
|
|
24026
|
-
dependencyExp.push(deferredDep.type);
|
|
24027
|
-
}
|
|
24532
|
+
if (!deferredDeps || deferredDeps.length === 0) {
|
|
24533
|
+
return TYPED_NULL_EXPR;
|
|
24534
|
+
}
|
|
24535
|
+
// This defer block has deps for which we need to generate dynamic imports.
|
|
24536
|
+
const dependencyExp = [];
|
|
24537
|
+
for (const deferredDep of deferredDeps) {
|
|
24538
|
+
if (deferredDep.isDeferrable) {
|
|
24539
|
+
// Callback function, e.g. `function(m) { return m.MyCmp; }`.
|
|
24540
|
+
const innerFn = fn([new FnParam('m', DYNAMIC_TYPE)], [new ReturnStatement(variable('m').prop(deferredDep.symbolName))]);
|
|
24541
|
+
// Dynamic import, e.g. `import('./a').then(...)`.
|
|
24542
|
+
const importExpr = (new DynamicImportExpr(deferredDep.importPath)).prop('then').callFn([innerFn]);
|
|
24543
|
+
dependencyExp.push(importExpr);
|
|
24544
|
+
}
|
|
24545
|
+
else {
|
|
24546
|
+
// Non-deferrable symbol, just use a reference to the type.
|
|
24547
|
+
dependencyExp.push(deferredDep.type);
|
|
24028
24548
|
}
|
|
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
24549
|
}
|
|
24034
|
-
|
|
24035
|
-
this.
|
|
24036
|
-
|
|
24037
|
-
|
|
24550
|
+
const depsFnExpr = fn([], [new ReturnStatement(literalArr(dependencyExp))], INFERRED_TYPE, null, name);
|
|
24551
|
+
this.constantPool.statements.push(depsFnExpr.toDeclStmt(name));
|
|
24552
|
+
return variable(name);
|
|
24553
|
+
}
|
|
24554
|
+
createDeferTriggerInstructions(deferredIndex, triggers, prefetch) {
|
|
24555
|
+
const { when, idle, immediate, timer, hover, interaction, viewport } = triggers;
|
|
24556
|
+
// `deferWhen(ctx.someValue)`
|
|
24557
|
+
if (when) {
|
|
24558
|
+
const value = when.value.visit(this._valueConverter);
|
|
24559
|
+
this.allocateBindingSlots(value);
|
|
24560
|
+
this.updateInstructionWithAdvance(deferredIndex, when.sourceSpan, prefetch ? Identifiers.deferPrefetchWhen : Identifiers.deferWhen, () => this.convertPropertyBinding(value));
|
|
24561
|
+
}
|
|
24562
|
+
// Note that we generate an implicit `on idle` if the `deferred` block has no triggers.
|
|
24563
|
+
// TODO(crisbeto): decide if this should be baked into the `defer` instruction.
|
|
24564
|
+
// `deferOnIdle()`
|
|
24565
|
+
if (idle || (!prefetch && Object.keys(triggers).length === 0)) {
|
|
24566
|
+
this.creationInstruction(idle?.sourceSpan || null, prefetch ? Identifiers.deferPrefetchOnIdle : Identifiers.deferOnIdle);
|
|
24567
|
+
}
|
|
24568
|
+
// `deferOnImmediate()`
|
|
24569
|
+
if (immediate) {
|
|
24570
|
+
this.creationInstruction(immediate.sourceSpan, prefetch ? Identifiers.deferPrefetchOnImmediate : Identifiers.deferOnImmediate);
|
|
24571
|
+
}
|
|
24572
|
+
// `deferOnTimer(1337)`
|
|
24573
|
+
if (timer) {
|
|
24574
|
+
this.creationInstruction(timer.sourceSpan, prefetch ? Identifiers.deferPrefetchOnTimer : Identifiers.deferOnTimer, [literal(timer.delay)]);
|
|
24575
|
+
}
|
|
24576
|
+
// `deferOnHover()`
|
|
24577
|
+
if (hover) {
|
|
24578
|
+
this.creationInstruction(hover.sourceSpan, prefetch ? Identifiers.deferPrefetchOnHover : Identifiers.deferOnHover);
|
|
24579
|
+
}
|
|
24580
|
+
// TODO(crisbeto): currently the reference is passed as a string.
|
|
24581
|
+
// Update this once we figure out how we should refer to the target.
|
|
24582
|
+
// `deferOnInteraction(target)`
|
|
24583
|
+
if (interaction) {
|
|
24584
|
+
this.creationInstruction(interaction.sourceSpan, prefetch ? Identifiers.deferPrefetchOnInteraction : Identifiers.deferOnInteraction, [literal(interaction.reference)]);
|
|
24585
|
+
}
|
|
24586
|
+
// TODO(crisbeto): currently the reference is passed as a string.
|
|
24587
|
+
// Update this once we figure out how we should refer to the target.
|
|
24588
|
+
// `deferOnViewport(target)`
|
|
24589
|
+
if (viewport) {
|
|
24590
|
+
this.creationInstruction(viewport.sourceSpan, prefetch ? Identifiers.deferPrefetchOnViewport : Identifiers.deferOnViewport, [literal(viewport.reference)]);
|
|
24591
|
+
}
|
|
24038
24592
|
}
|
|
24039
|
-
// TODO: implement nested deferred block instructions.
|
|
24040
|
-
visitDeferredTrigger(trigger) { }
|
|
24041
|
-
visitDeferredBlockPlaceholder(block) { }
|
|
24042
|
-
visitDeferredBlockError(block) { }
|
|
24043
|
-
visitDeferredBlockLoading(block) { }
|
|
24044
24593
|
allocateDataSlot() {
|
|
24045
24594
|
return this._dataIndex++;
|
|
24046
24595
|
}
|
|
24596
|
+
// TODO: implement control flow instructions
|
|
24597
|
+
visitSwitchBlock(block) { }
|
|
24598
|
+
visitSwitchBlockCase(block) { }
|
|
24599
|
+
visitForLoopBlock(block) { }
|
|
24600
|
+
visitForLoopBlockEmpty(block) { }
|
|
24601
|
+
visitIfBlock(block) { }
|
|
24602
|
+
visitIfBlockBranch(block) { }
|
|
24047
24603
|
getConstCount() {
|
|
24048
24604
|
return this._dataIndex;
|
|
24049
24605
|
}
|
|
@@ -24293,7 +24849,8 @@ class TemplateDefinitionBuilder {
|
|
|
24293
24849
|
return literal(consts.push(expression) - 1);
|
|
24294
24850
|
}
|
|
24295
24851
|
addAttrsToConsts(attrs) {
|
|
24296
|
-
return attrs.length > 0 ? this.addToConsts(literalArr(attrs)) :
|
|
24852
|
+
return attrs !== null && attrs.length > 0 ? this.addToConsts(literalArr(attrs)) :
|
|
24853
|
+
TYPED_NULL_EXPR;
|
|
24297
24854
|
}
|
|
24298
24855
|
prepareRefsArray(references) {
|
|
24299
24856
|
if (!references || references.length === 0) {
|
|
@@ -25137,9 +25694,17 @@ function compileComponentFromMetadata(meta, constantPool, bindingParser) {
|
|
|
25137
25694
|
}
|
|
25138
25695
|
definitionMap.set('template', templateFn);
|
|
25139
25696
|
}
|
|
25140
|
-
if (meta.
|
|
25697
|
+
if (meta.declarationListEmitMode !== 3 /* DeclarationListEmitMode.RuntimeResolved */ &&
|
|
25698
|
+
meta.declarations.length > 0) {
|
|
25141
25699
|
definitionMap.set('dependencies', compileDeclarationList(literalArr(meta.declarations.map(decl => decl.type)), meta.declarationListEmitMode));
|
|
25142
25700
|
}
|
|
25701
|
+
else if (meta.declarationListEmitMode === 3 /* DeclarationListEmitMode.RuntimeResolved */) {
|
|
25702
|
+
const args = [meta.type.value];
|
|
25703
|
+
if (meta.rawImports) {
|
|
25704
|
+
args.push(meta.rawImports);
|
|
25705
|
+
}
|
|
25706
|
+
definitionMap.set('dependencies', importExpr(Identifiers.getComponentDepsFactory).callFn(args));
|
|
25707
|
+
}
|
|
25143
25708
|
if (meta.encapsulation === null) {
|
|
25144
25709
|
meta.encapsulation = ViewEncapsulation.Emulated;
|
|
25145
25710
|
}
|
|
@@ -25211,6 +25776,8 @@ function compileDeclarationList(list, mode) {
|
|
|
25211
25776
|
// directives: function () { return [MyDir].map(ng.resolveForwardRef); }
|
|
25212
25777
|
const resolvedList = list.prop('map').callFn([importExpr(Identifiers.resolveForwardRef)]);
|
|
25213
25778
|
return fn([], [new ReturnStatement(resolvedList)]);
|
|
25779
|
+
case 3 /* DeclarationListEmitMode.RuntimeResolved */:
|
|
25780
|
+
throw new Error(`Unsupported with an array of pre-resolved dependencies`);
|
|
25214
25781
|
}
|
|
25215
25782
|
}
|
|
25216
25783
|
function prepareQueryParams(query, constantPool) {
|
|
@@ -26331,7 +26898,7 @@ function publishFacade(global) {
|
|
|
26331
26898
|
* @description
|
|
26332
26899
|
* Entry point for all public APIs of the compiler package.
|
|
26333
26900
|
*/
|
|
26334
|
-
const VERSION = new Version('
|
|
26901
|
+
const VERSION = new Version('17.0.0-next.0');
|
|
26335
26902
|
|
|
26336
26903
|
class CompilerConfig {
|
|
26337
26904
|
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, useJit = true, missingTranslation = null, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
@@ -27891,6 +28458,25 @@ class Scope {
|
|
|
27891
28458
|
visitDeferredBlockLoading(block) {
|
|
27892
28459
|
block.children.forEach(node => node.visit(this));
|
|
27893
28460
|
}
|
|
28461
|
+
visitSwitchBlock(block) {
|
|
28462
|
+
block.cases.forEach(node => node.visit(this));
|
|
28463
|
+
}
|
|
28464
|
+
visitSwitchBlockCase(block) {
|
|
28465
|
+
block.children.forEach(node => node.visit(this));
|
|
28466
|
+
}
|
|
28467
|
+
visitForLoopBlock(block) {
|
|
28468
|
+
block.children.forEach(node => node.visit(this));
|
|
28469
|
+
block.empty?.visit(this);
|
|
28470
|
+
}
|
|
28471
|
+
visitForLoopBlockEmpty(block) {
|
|
28472
|
+
block.children.forEach(node => node.visit(this));
|
|
28473
|
+
}
|
|
28474
|
+
visitIfBlock(block) {
|
|
28475
|
+
block.branches.forEach(node => node.visit(this));
|
|
28476
|
+
}
|
|
28477
|
+
visitIfBlockBranch(block) {
|
|
28478
|
+
block.children.forEach(node => node.visit(this));
|
|
28479
|
+
}
|
|
27894
28480
|
// Unused visitors.
|
|
27895
28481
|
visitContent(content) { }
|
|
27896
28482
|
visitBoundAttribute(attr) { }
|
|
@@ -28045,9 +28631,10 @@ class DirectiveBinder {
|
|
|
28045
28631
|
node.children.forEach(child => child.visit(this));
|
|
28046
28632
|
}
|
|
28047
28633
|
visitDeferredBlock(deferred) {
|
|
28634
|
+
const wasInDeferBlock = this.isInDeferBlock;
|
|
28048
28635
|
this.isInDeferBlock = true;
|
|
28049
28636
|
deferred.children.forEach(child => child.visit(this));
|
|
28050
|
-
this.isInDeferBlock =
|
|
28637
|
+
this.isInDeferBlock = wasInDeferBlock;
|
|
28051
28638
|
deferred.placeholder?.visit(this);
|
|
28052
28639
|
deferred.loading?.visit(this);
|
|
28053
28640
|
deferred.error?.visit(this);
|
|
@@ -28061,6 +28648,25 @@ class DirectiveBinder {
|
|
|
28061
28648
|
visitDeferredBlockLoading(block) {
|
|
28062
28649
|
block.children.forEach(child => child.visit(this));
|
|
28063
28650
|
}
|
|
28651
|
+
visitSwitchBlock(block) {
|
|
28652
|
+
block.cases.forEach(node => node.visit(this));
|
|
28653
|
+
}
|
|
28654
|
+
visitSwitchBlockCase(block) {
|
|
28655
|
+
block.children.forEach(node => node.visit(this));
|
|
28656
|
+
}
|
|
28657
|
+
visitForLoopBlock(block) {
|
|
28658
|
+
block.children.forEach(node => node.visit(this));
|
|
28659
|
+
block.empty?.visit(this);
|
|
28660
|
+
}
|
|
28661
|
+
visitForLoopBlockEmpty(block) {
|
|
28662
|
+
block.children.forEach(node => node.visit(this));
|
|
28663
|
+
}
|
|
28664
|
+
visitIfBlock(block) {
|
|
28665
|
+
block.branches.forEach(node => node.visit(this));
|
|
28666
|
+
}
|
|
28667
|
+
visitIfBlockBranch(block) {
|
|
28668
|
+
block.children.forEach(node => node.visit(this));
|
|
28669
|
+
}
|
|
28064
28670
|
// Unused visitors.
|
|
28065
28671
|
visitContent(content) { }
|
|
28066
28672
|
visitVariable(variable) { }
|
|
@@ -28197,11 +28803,10 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
28197
28803
|
}
|
|
28198
28804
|
visitDeferredBlock(deferred) {
|
|
28199
28805
|
this.deferBlocks.add(deferred);
|
|
28806
|
+
const wasInDeferBlock = this.isInDeferBlock;
|
|
28200
28807
|
this.isInDeferBlock = true;
|
|
28201
28808
|
deferred.children.forEach(this.visitNode);
|
|
28202
|
-
this.isInDeferBlock =
|
|
28203
|
-
deferred.triggers.forEach(this.visitNode);
|
|
28204
|
-
deferred.prefetchTriggers.forEach(this.visitNode);
|
|
28809
|
+
this.isInDeferBlock = wasInDeferBlock;
|
|
28205
28810
|
deferred.placeholder && this.visitNode(deferred.placeholder);
|
|
28206
28811
|
deferred.loading && this.visitNode(deferred.loading);
|
|
28207
28812
|
deferred.error && this.visitNode(deferred.error);
|
|
@@ -28220,6 +28825,29 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
28220
28825
|
visitDeferredBlockLoading(block) {
|
|
28221
28826
|
block.children.forEach(this.visitNode);
|
|
28222
28827
|
}
|
|
28828
|
+
visitSwitchBlock(block) {
|
|
28829
|
+
block.expression.visit(this);
|
|
28830
|
+
block.cases.forEach(this.visitNode);
|
|
28831
|
+
}
|
|
28832
|
+
visitSwitchBlockCase(block) {
|
|
28833
|
+
block.expression?.visit(this);
|
|
28834
|
+
block.children.forEach(this.visitNode);
|
|
28835
|
+
}
|
|
28836
|
+
visitForLoopBlock(block) {
|
|
28837
|
+
block.expression.visit(this);
|
|
28838
|
+
block.children.forEach(this.visitNode);
|
|
28839
|
+
block.empty?.visit(this);
|
|
28840
|
+
}
|
|
28841
|
+
visitForLoopBlockEmpty(block) {
|
|
28842
|
+
block.children.forEach(this.visitNode);
|
|
28843
|
+
}
|
|
28844
|
+
visitIfBlock(block) {
|
|
28845
|
+
block.branches.forEach(node => node.visit(this));
|
|
28846
|
+
}
|
|
28847
|
+
visitIfBlockBranch(block) {
|
|
28848
|
+
block.expression?.visit(this);
|
|
28849
|
+
block.children.forEach(node => node.visit(this));
|
|
28850
|
+
}
|
|
28223
28851
|
visitBoundText(text) {
|
|
28224
28852
|
text.value.visit(this);
|
|
28225
28853
|
}
|
|
@@ -28362,6 +28990,60 @@ function compileClassMetadata(metadata) {
|
|
|
28362
28990
|
const iife = fn([], [devOnlyGuardedExpression(fnCall).toStmt()]);
|
|
28363
28991
|
return iife.callFn([]);
|
|
28364
28992
|
}
|
|
28993
|
+
/**
|
|
28994
|
+
* Wraps the `setClassMetadata` function with extra logic that dynamically
|
|
28995
|
+
* loads dependencies from `{#defer}` blocks.
|
|
28996
|
+
*
|
|
28997
|
+
* Generates a call like this:
|
|
28998
|
+
* ```
|
|
28999
|
+
* setClassMetadataAsync(type, () => {
|
|
29000
|
+
* return [
|
|
29001
|
+
* import('./cmp-a').then(m => m.CmpA);
|
|
29002
|
+
* import('./cmp-b').then(m => m.CmpB);
|
|
29003
|
+
* ];
|
|
29004
|
+
* }, (CmpA, CmpB) => {
|
|
29005
|
+
* setClassMetadata(type, decorators, ctorParameters, propParameters);
|
|
29006
|
+
* });
|
|
29007
|
+
* ```
|
|
29008
|
+
*
|
|
29009
|
+
* Similar to the `setClassMetadata` call, it's wrapped into the `ngDevMode`
|
|
29010
|
+
* check to tree-shake away this code in production mode.
|
|
29011
|
+
*/
|
|
29012
|
+
function compileComponentClassMetadata(metadata, deferrableTypes) {
|
|
29013
|
+
if (deferrableTypes.size === 0) {
|
|
29014
|
+
// If there are no deferrable symbols - just generate a regular `setClassMetadata` call.
|
|
29015
|
+
return compileClassMetadata(metadata);
|
|
29016
|
+
}
|
|
29017
|
+
const dynamicImports = [];
|
|
29018
|
+
const importedSymbols = [];
|
|
29019
|
+
for (const [symbolName, importPath] of deferrableTypes) {
|
|
29020
|
+
// e.g. `function(m) { return m.CmpA; }`
|
|
29021
|
+
const innerFn = fn([new FnParam('m', DYNAMIC_TYPE)], [new ReturnStatement(variable('m').prop(symbolName))]);
|
|
29022
|
+
// e.g. `import('./cmp-a').then(...)`
|
|
29023
|
+
const importExpr = (new DynamicImportExpr(importPath)).prop('then').callFn([innerFn]);
|
|
29024
|
+
dynamicImports.push(importExpr);
|
|
29025
|
+
importedSymbols.push(new FnParam(symbolName, DYNAMIC_TYPE));
|
|
29026
|
+
}
|
|
29027
|
+
// e.g. `function() { return [ ... ]; }`
|
|
29028
|
+
const dependencyLoadingFn = fn([], [new ReturnStatement(literalArr(dynamicImports))]);
|
|
29029
|
+
// e.g. `setClassMetadata(...)`
|
|
29030
|
+
const setClassMetadataCall = importExpr(Identifiers.setClassMetadata).callFn([
|
|
29031
|
+
metadata.type,
|
|
29032
|
+
metadata.decorators,
|
|
29033
|
+
metadata.ctorParameters ?? literal(null),
|
|
29034
|
+
metadata.propDecorators ?? literal(null),
|
|
29035
|
+
]);
|
|
29036
|
+
// e.g. `function(CmpA) { setClassMetadata(...); }`
|
|
29037
|
+
const setClassMetaWrapper = fn(importedSymbols, [setClassMetadataCall.toStmt()]);
|
|
29038
|
+
// Final `setClassMetadataAsync()` call with all arguments
|
|
29039
|
+
const setClassMetaAsync = importExpr(Identifiers.setClassMetadataAsync).callFn([
|
|
29040
|
+
metadata.type, dependencyLoadingFn, setClassMetaWrapper
|
|
29041
|
+
]);
|
|
29042
|
+
// Generate an ngDevMode guarded call to `setClassMetadataAsync` with
|
|
29043
|
+
// the class identifier and its metadata, so that this call can be tree-shaken.
|
|
29044
|
+
const iife = fn([], [devOnlyGuardedExpression(setClassMetaAsync).toStmt()]);
|
|
29045
|
+
return iife.callFn([]);
|
|
29046
|
+
}
|
|
28365
29047
|
|
|
28366
29048
|
/**
|
|
28367
29049
|
* Every time we make a breaking change to the declaration interface or partial-linker behavior, we
|
|
@@ -28374,7 +29056,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
|
|
|
28374
29056
|
function compileDeclareClassMetadata(metadata) {
|
|
28375
29057
|
const definitionMap = new DefinitionMap();
|
|
28376
29058
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
28377
|
-
definitionMap.set('version', literal('
|
|
29059
|
+
definitionMap.set('version', literal('17.0.0-next.0'));
|
|
28378
29060
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
28379
29061
|
definitionMap.set('type', metadata.type);
|
|
28380
29062
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -28477,7 +29159,7 @@ function compileDeclareDirectiveFromMetadata(meta) {
|
|
|
28477
29159
|
function createDirectiveDefinitionMap(meta) {
|
|
28478
29160
|
const definitionMap = new DefinitionMap();
|
|
28479
29161
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
|
|
28480
|
-
definitionMap.set('version', literal('
|
|
29162
|
+
definitionMap.set('version', literal('17.0.0-next.0'));
|
|
28481
29163
|
// e.g. `type: MyDirective`
|
|
28482
29164
|
definitionMap.set('type', meta.type.value);
|
|
28483
29165
|
if (meta.isStandalone) {
|
|
@@ -28668,6 +29350,9 @@ function compileUsedDependenciesMetadata(meta) {
|
|
|
28668
29350
|
const wrapType = meta.declarationListEmitMode !== 0 /* DeclarationListEmitMode.Direct */ ?
|
|
28669
29351
|
generateForwardRef :
|
|
28670
29352
|
(expr) => expr;
|
|
29353
|
+
if (meta.declarationListEmitMode === 3 /* DeclarationListEmitMode.RuntimeResolved */) {
|
|
29354
|
+
throw new Error(`Unsupported emit mode`);
|
|
29355
|
+
}
|
|
28671
29356
|
return toOptionalLiteralArray(meta.declarations, decl => {
|
|
28672
29357
|
switch (decl.kind) {
|
|
28673
29358
|
case R3TemplateDependencyKind.Directive:
|
|
@@ -28705,7 +29390,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
28705
29390
|
function compileDeclareFactoryFunction(meta) {
|
|
28706
29391
|
const definitionMap = new DefinitionMap();
|
|
28707
29392
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
28708
|
-
definitionMap.set('version', literal('
|
|
29393
|
+
definitionMap.set('version', literal('17.0.0-next.0'));
|
|
28709
29394
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
28710
29395
|
definitionMap.set('type', meta.type.value);
|
|
28711
29396
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -28740,7 +29425,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
28740
29425
|
function createInjectableDefinitionMap(meta) {
|
|
28741
29426
|
const definitionMap = new DefinitionMap();
|
|
28742
29427
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
28743
|
-
definitionMap.set('version', literal('
|
|
29428
|
+
definitionMap.set('version', literal('17.0.0-next.0'));
|
|
28744
29429
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
28745
29430
|
definitionMap.set('type', meta.type.value);
|
|
28746
29431
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -28791,7 +29476,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
28791
29476
|
function createInjectorDefinitionMap(meta) {
|
|
28792
29477
|
const definitionMap = new DefinitionMap();
|
|
28793
29478
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
28794
|
-
definitionMap.set('version', literal('
|
|
29479
|
+
definitionMap.set('version', literal('17.0.0-next.0'));
|
|
28795
29480
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
28796
29481
|
definitionMap.set('type', meta.type.value);
|
|
28797
29482
|
definitionMap.set('providers', meta.providers);
|
|
@@ -28824,7 +29509,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
28824
29509
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
28825
29510
|
}
|
|
28826
29511
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
28827
|
-
definitionMap.set('version', literal('
|
|
29512
|
+
definitionMap.set('version', literal('17.0.0-next.0'));
|
|
28828
29513
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
28829
29514
|
definitionMap.set('type', meta.type.value);
|
|
28830
29515
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -28875,7 +29560,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
28875
29560
|
function createPipeDefinitionMap(meta) {
|
|
28876
29561
|
const definitionMap = new DefinitionMap();
|
|
28877
29562
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
28878
|
-
definitionMap.set('version', literal('
|
|
29563
|
+
definitionMap.set('version', literal('17.0.0-next.0'));
|
|
28879
29564
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
28880
29565
|
// e.g. `type: MyPipe`
|
|
28881
29566
|
definitionMap.set('type', meta.type.value);
|
|
@@ -28908,5 +29593,5 @@ publishFacade(_global);
|
|
|
28908
29593
|
|
|
28909
29594
|
// This file is not used to build this module. It is only used during editing
|
|
28910
29595
|
|
|
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 };
|
|
29596
|
+
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, ForLoopBlock as TmplAstForLoopBlock, ForLoopBlockEmpty as TmplAstForLoopBlockEmpty, HoverDeferredTrigger as TmplAstHoverDeferredTrigger, Icu$1 as TmplAstIcu, IdleDeferredTrigger as TmplAstIdleDeferredTrigger, IfBlock as TmplAstIfBlock, IfBlockBranch as TmplAstIfBlockBranch, ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger, InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger, RecursiveVisitor$1 as TmplAstRecursiveVisitor, Reference as TmplAstReference, SwitchBlock as TmplAstSwitchBlock, SwitchBlockCase as TmplAstSwitchBlockCase, 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, compileComponentClassMetadata, 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 };
|
|
28912
29597
|
//# sourceMappingURL=compiler.mjs.map
|