@angular/compiler 17.0.0-next.6 → 17.0.0-next.8
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 +4 -3
- package/esm2022/src/config.mjs +2 -4
- package/esm2022/src/injectable_compiler_2.mjs +3 -6
- package/esm2022/src/jit_compiler_facade.mjs +2 -7
- package/esm2022/src/ml_parser/lexer.mjs +19 -11
- package/esm2022/src/ml_parser/parser.mjs +28 -10
- package/esm2022/src/ml_parser/tokens.mjs +1 -1
- package/esm2022/src/output/abstract_emitter.mjs +8 -1
- package/esm2022/src/render3/partial/class_metadata.mjs +1 -1
- package/esm2022/src/render3/partial/component.mjs +45 -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 +37 -19
- package/esm2022/src/render3/r3_class_debug_info_compiler.mjs +36 -0
- package/esm2022/src/render3/r3_control_flow.mjs +40 -23
- package/esm2022/src/render3/r3_deferred_blocks.mjs +13 -3
- package/esm2022/src/render3/r3_factory.mjs +2 -2
- package/esm2022/src/render3/r3_identifiers.mjs +3 -1
- package/esm2022/src/render3/r3_template_transform.mjs +19 -23
- package/esm2022/src/render3/util.mjs +3 -3
- package/esm2022/src/render3/view/compiler.mjs +8 -6
- package/esm2022/src/render3/view/t2_binder.mjs +8 -7
- package/esm2022/src/render3/view/template.mjs +36 -27
- package/esm2022/src/render3/view/util.mjs +8 -2
- package/esm2022/src/template/pipeline/ir/src/enums.mjs +42 -9
- package/esm2022/src/template/pipeline/ir/src/expression.mjs +61 -16
- package/esm2022/src/template/pipeline/ir/src/operations.mjs +2 -2
- package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +55 -12
- package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +35 -4
- package/esm2022/src/template/pipeline/ir/src/traits.mjs +17 -2
- package/esm2022/src/template/pipeline/ir/src/variable.mjs +6 -2
- package/esm2022/src/template/pipeline/src/conversion.mjs +3 -2
- package/esm2022/src/template/pipeline/src/emit.mjs +16 -10
- package/esm2022/src/template/pipeline/src/ingest.mjs +159 -18
- package/esm2022/src/template/pipeline/src/instruction.mjs +44 -7
- package/esm2022/src/template/pipeline/src/phases/apply_i18n_expressions.mjs +37 -0
- package/esm2022/src/template/pipeline/src/phases/assign_i18n_slot_dependencies.mjs +33 -0
- package/esm2022/src/template/pipeline/src/phases/chaining.mjs +13 -12
- package/esm2022/src/template/pipeline/src/phases/conditionals.mjs +22 -9
- package/esm2022/src/template/pipeline/src/phases/empty_elements.mjs +14 -3
- package/esm2022/src/template/pipeline/src/phases/generate_variables.mjs +6 -2
- package/esm2022/src/template/pipeline/src/phases/has_const_trait_collection.mjs +34 -0
- package/esm2022/src/template/pipeline/src/phases/host_style_property_parsing.mjs +6 -1
- package/esm2022/src/template/pipeline/src/phases/i18n_const_collection.mjs +3 -3
- package/esm2022/src/template/pipeline/src/phases/i18n_message_extraction.mjs +18 -15
- package/esm2022/src/template/pipeline/src/phases/i18n_text_extraction.mjs +31 -5
- package/esm2022/src/template/pipeline/src/phases/naming.mjs +3 -3
- package/esm2022/src/template/pipeline/src/phases/ng_container.mjs +6 -1
- package/esm2022/src/template/pipeline/src/phases/propagate_i18n_blocks.mjs +57 -0
- package/esm2022/src/template/pipeline/src/phases/propagate_i18n_placeholders.mjs +39 -0
- package/esm2022/src/template/pipeline/src/phases/pure_function_extraction.mjs +4 -4
- package/esm2022/src/template/pipeline/src/phases/reify.mjs +25 -10
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_placeholders.mjs +163 -36
- package/esm2022/src/template/pipeline/src/phases/slot_allocation.mjs +5 -5
- package/esm2022/src/template/pipeline/src/phases/temporary_variables.mjs +53 -38
- package/esm2022/src/template/pipeline/src/phases/var_counting.mjs +10 -1
- package/esm2022/src/template/pipeline/src/phases/variable_optimization.mjs +9 -1
- package/esm2022/src/version.mjs +1 -1
- package/fesm2022/compiler.mjs +1406 -550
- package/fesm2022/compiler.mjs.map +1 -1
- package/index.d.ts +81 -18
- package/package.json +2 -8
- package/esm2022/src/template/pipeline/src/phases/generate_i18n_blocks.mjs +0 -38
- package/esm2022/src/template/pipeline/src/phases/no_listeners_on_templates.mjs +0 -32
- package/esm2022/testing/index.mjs +0 -13
- package/esm2022/testing/public_api.mjs +0 -16
- package/esm2022/testing/src/testing.mjs +0 -29
- package/esm2022/testing/testing.mjs +0 -5
- package/fesm2022/testing.mjs +0 -39
- package/fesm2022/testing.mjs.map +0 -1
- package/testing/index.d.ts +0 -25
package/fesm2022/compiler.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v17.0.0-next.
|
|
2
|
+
* @license Angular v17.0.0-next.8
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -2482,6 +2482,7 @@ class Identifiers {
|
|
|
2482
2482
|
static { this.deferPrefetchOnHover = { name: 'ɵɵdeferPrefetchOnHover', moduleName: CORE }; }
|
|
2483
2483
|
static { this.deferPrefetchOnInteraction = { name: 'ɵɵdeferPrefetchOnInteraction', moduleName: CORE }; }
|
|
2484
2484
|
static { this.deferPrefetchOnViewport = { name: 'ɵɵdeferPrefetchOnViewport', moduleName: CORE }; }
|
|
2485
|
+
static { this.deferEnableTimerScheduling = { name: 'ɵɵdeferEnableTimerScheduling', moduleName: CORE }; }
|
|
2485
2486
|
static { this.conditional = { name: 'ɵɵconditional', moduleName: CORE }; }
|
|
2486
2487
|
static { this.repeater = { name: 'ɵɵrepeater', moduleName: CORE }; }
|
|
2487
2488
|
static { this.repeaterCreate = { name: 'ɵɵrepeaterCreate', moduleName: CORE }; }
|
|
@@ -2605,6 +2606,7 @@ class Identifiers {
|
|
|
2605
2606
|
static { this.declareClassMetadata = { name: 'ɵɵngDeclareClassMetadata', moduleName: CORE }; }
|
|
2606
2607
|
static { this.setClassMetadata = { name: 'ɵsetClassMetadata', moduleName: CORE }; }
|
|
2607
2608
|
static { this.setClassMetadataAsync = { name: 'ɵsetClassMetadataAsync', moduleName: CORE }; }
|
|
2609
|
+
static { this.setClassDebugInfo = { name: 'ɵsetClassDebugInfo', moduleName: CORE }; }
|
|
2608
2610
|
static { this.queryRefresh = { name: 'ɵɵqueryRefresh', moduleName: CORE }; }
|
|
2609
2611
|
static { this.viewQuery = { name: 'ɵɵviewQuery', moduleName: CORE }; }
|
|
2610
2612
|
static { this.loadQuery = { name: 'ɵɵloadQuery', moduleName: CORE }; }
|
|
@@ -3139,7 +3141,14 @@ class AbstractEmitterVisitor {
|
|
|
3139
3141
|
return null;
|
|
3140
3142
|
}
|
|
3141
3143
|
visitInvokeFunctionExpr(expr, ctx) {
|
|
3144
|
+
const shouldParenthesize = expr.fn instanceof ArrowFunctionExpr;
|
|
3145
|
+
if (shouldParenthesize) {
|
|
3146
|
+
ctx.print(expr.fn, '(');
|
|
3147
|
+
}
|
|
3142
3148
|
expr.fn.visitExpression(this, ctx);
|
|
3149
|
+
if (shouldParenthesize) {
|
|
3150
|
+
ctx.print(expr.fn, ')');
|
|
3151
|
+
}
|
|
3143
3152
|
ctx.print(expr, `(`);
|
|
3144
3153
|
this.visitAllExpressions(expr.args, ctx, ',');
|
|
3145
3154
|
ctx.print(expr, `)`);
|
|
@@ -3438,7 +3447,7 @@ function wrapReference(value) {
|
|
|
3438
3447
|
}
|
|
3439
3448
|
function refsToArray(refs, shouldForwardDeclare) {
|
|
3440
3449
|
const values = literalArr(refs.map(ref => ref.value));
|
|
3441
|
-
return shouldForwardDeclare ?
|
|
3450
|
+
return shouldForwardDeclare ? arrowFn([], values) : values;
|
|
3442
3451
|
}
|
|
3443
3452
|
function createMayBeForwardRefExpression(expression, forwardRef) {
|
|
3444
3453
|
return { expression, forwardRef };
|
|
@@ -3471,7 +3480,7 @@ function convertFromMaybeForwardRefExpression({ expression, forwardRef }) {
|
|
|
3471
3480
|
* ```
|
|
3472
3481
|
*/
|
|
3473
3482
|
function generateForwardRef(expr) {
|
|
3474
|
-
return importExpr(Identifiers.forwardRef).callFn([
|
|
3483
|
+
return importExpr(Identifiers.forwardRef).callFn([arrowFn([], expr)]);
|
|
3475
3484
|
}
|
|
3476
3485
|
|
|
3477
3486
|
var R3FactoryDelegateType;
|
|
@@ -3559,7 +3568,7 @@ function compileFactoryFunction(meta) {
|
|
|
3559
3568
|
if (baseFactoryVar !== null) {
|
|
3560
3569
|
// There is a base factory variable so wrap its declaration along with the factory function into
|
|
3561
3570
|
// an IIFE.
|
|
3562
|
-
factoryFn =
|
|
3571
|
+
factoryFn = arrowFn([], [
|
|
3563
3572
|
new DeclareVarStmt(baseFactoryVar.name), new ReturnStatement(factoryFn)
|
|
3564
3573
|
]).callFn([], /* sourceSpan */ undefined, /* pure */ true);
|
|
3565
3574
|
}
|
|
@@ -3861,12 +3870,13 @@ class DeferredBlockError {
|
|
|
3861
3870
|
}
|
|
3862
3871
|
}
|
|
3863
3872
|
class DeferredBlock {
|
|
3864
|
-
constructor(children, triggers, prefetchTriggers, placeholder, loading, error, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3873
|
+
constructor(children, triggers, prefetchTriggers, placeholder, loading, error, sourceSpan, mainBlockSpan, startSourceSpan, endSourceSpan) {
|
|
3865
3874
|
this.children = children;
|
|
3866
3875
|
this.placeholder = placeholder;
|
|
3867
3876
|
this.loading = loading;
|
|
3868
3877
|
this.error = error;
|
|
3869
3878
|
this.sourceSpan = sourceSpan;
|
|
3879
|
+
this.mainBlockSpan = mainBlockSpan;
|
|
3870
3880
|
this.startSourceSpan = startSourceSpan;
|
|
3871
3881
|
this.endSourceSpan = endSourceSpan;
|
|
3872
3882
|
this.triggers = triggers;
|
|
@@ -3883,20 +3893,23 @@ class DeferredBlock {
|
|
|
3883
3893
|
this.visitTriggers(this.definedTriggers, this.triggers, visitor);
|
|
3884
3894
|
this.visitTriggers(this.definedPrefetchTriggers, this.prefetchTriggers, visitor);
|
|
3885
3895
|
visitAll$1(visitor, this.children);
|
|
3886
|
-
this.placeholder
|
|
3887
|
-
|
|
3888
|
-
this.error && visitor.visitDeferredBlockError(this.error);
|
|
3896
|
+
const remainingBlocks = [this.placeholder, this.loading, this.error].filter(x => x !== null);
|
|
3897
|
+
visitAll$1(visitor, remainingBlocks);
|
|
3889
3898
|
}
|
|
3890
3899
|
visitTriggers(keys, triggers, visitor) {
|
|
3891
|
-
|
|
3892
|
-
visitor.visitDeferredTrigger(triggers[key]);
|
|
3893
|
-
}
|
|
3900
|
+
visitAll$1(visitor, keys.map(k => triggers[k]));
|
|
3894
3901
|
}
|
|
3895
3902
|
}
|
|
3896
3903
|
class SwitchBlock {
|
|
3897
|
-
constructor(expression, cases,
|
|
3904
|
+
constructor(expression, cases,
|
|
3905
|
+
/**
|
|
3906
|
+
* These blocks are only captured to allow for autocompletion in the language service. They
|
|
3907
|
+
* aren't meant to be processed in any other way.
|
|
3908
|
+
*/
|
|
3909
|
+
unknownBlocks, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3898
3910
|
this.expression = expression;
|
|
3899
3911
|
this.cases = cases;
|
|
3912
|
+
this.unknownBlocks = unknownBlocks;
|
|
3900
3913
|
this.sourceSpan = sourceSpan;
|
|
3901
3914
|
this.startSourceSpan = startSourceSpan;
|
|
3902
3915
|
this.endSourceSpan = endSourceSpan;
|
|
@@ -3906,18 +3919,19 @@ class SwitchBlock {
|
|
|
3906
3919
|
}
|
|
3907
3920
|
}
|
|
3908
3921
|
class SwitchBlockCase {
|
|
3909
|
-
constructor(expression, children, sourceSpan, startSourceSpan) {
|
|
3922
|
+
constructor(expression, children, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3910
3923
|
this.expression = expression;
|
|
3911
3924
|
this.children = children;
|
|
3912
3925
|
this.sourceSpan = sourceSpan;
|
|
3913
3926
|
this.startSourceSpan = startSourceSpan;
|
|
3927
|
+
this.endSourceSpan = endSourceSpan;
|
|
3914
3928
|
}
|
|
3915
3929
|
visit(visitor) {
|
|
3916
3930
|
return visitor.visitSwitchBlockCase(this);
|
|
3917
3931
|
}
|
|
3918
3932
|
}
|
|
3919
3933
|
class ForLoopBlock {
|
|
3920
|
-
constructor(item, expression, trackBy, contextVariables, children, empty, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3934
|
+
constructor(item, expression, trackBy, contextVariables, children, empty, sourceSpan, mainBlockSpan, startSourceSpan, endSourceSpan) {
|
|
3921
3935
|
this.item = item;
|
|
3922
3936
|
this.expression = expression;
|
|
3923
3937
|
this.trackBy = trackBy;
|
|
@@ -3925,6 +3939,7 @@ class ForLoopBlock {
|
|
|
3925
3939
|
this.children = children;
|
|
3926
3940
|
this.empty = empty;
|
|
3927
3941
|
this.sourceSpan = sourceSpan;
|
|
3942
|
+
this.mainBlockSpan = mainBlockSpan;
|
|
3928
3943
|
this.startSourceSpan = startSourceSpan;
|
|
3929
3944
|
this.endSourceSpan = endSourceSpan;
|
|
3930
3945
|
}
|
|
@@ -3933,10 +3948,11 @@ class ForLoopBlock {
|
|
|
3933
3948
|
}
|
|
3934
3949
|
}
|
|
3935
3950
|
class ForLoopBlockEmpty {
|
|
3936
|
-
constructor(children, sourceSpan, startSourceSpan) {
|
|
3951
|
+
constructor(children, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3937
3952
|
this.children = children;
|
|
3938
3953
|
this.sourceSpan = sourceSpan;
|
|
3939
3954
|
this.startSourceSpan = startSourceSpan;
|
|
3955
|
+
this.endSourceSpan = endSourceSpan;
|
|
3940
3956
|
}
|
|
3941
3957
|
visit(visitor) {
|
|
3942
3958
|
return visitor.visitForLoopBlockEmpty(this);
|
|
@@ -3954,17 +3970,27 @@ class IfBlock {
|
|
|
3954
3970
|
}
|
|
3955
3971
|
}
|
|
3956
3972
|
class IfBlockBranch {
|
|
3957
|
-
constructor(expression, children, expressionAlias, sourceSpan, startSourceSpan) {
|
|
3973
|
+
constructor(expression, children, expressionAlias, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3958
3974
|
this.expression = expression;
|
|
3959
3975
|
this.children = children;
|
|
3960
3976
|
this.expressionAlias = expressionAlias;
|
|
3961
3977
|
this.sourceSpan = sourceSpan;
|
|
3962
3978
|
this.startSourceSpan = startSourceSpan;
|
|
3979
|
+
this.endSourceSpan = endSourceSpan;
|
|
3963
3980
|
}
|
|
3964
3981
|
visit(visitor) {
|
|
3965
3982
|
return visitor.visitIfBlockBranch(this);
|
|
3966
3983
|
}
|
|
3967
3984
|
}
|
|
3985
|
+
class UnknownBlock {
|
|
3986
|
+
constructor(name, sourceSpan) {
|
|
3987
|
+
this.name = name;
|
|
3988
|
+
this.sourceSpan = sourceSpan;
|
|
3989
|
+
}
|
|
3990
|
+
visit(visitor) {
|
|
3991
|
+
return visitor.visitUnknownBlock(this);
|
|
3992
|
+
}
|
|
3993
|
+
}
|
|
3968
3994
|
class Template {
|
|
3969
3995
|
constructor(
|
|
3970
3996
|
// tagName is the name of the container element, if applicable.
|
|
@@ -4071,10 +4097,9 @@ class RecursiveVisitor$1 {
|
|
|
4071
4097
|
visitAll$1(this, block.children);
|
|
4072
4098
|
}
|
|
4073
4099
|
visitForLoopBlock(block) {
|
|
4074
|
-
block.item.
|
|
4075
|
-
|
|
4076
|
-
visitAll$1(this,
|
|
4077
|
-
block.empty?.visit(this);
|
|
4100
|
+
const blockItems = [block.item, ...Object.values(block.contextVariables), ...block.children];
|
|
4101
|
+
block.empty && blockItems.push(block.empty);
|
|
4102
|
+
visitAll$1(this, blockItems);
|
|
4078
4103
|
}
|
|
4079
4104
|
visitForLoopBlockEmpty(block) {
|
|
4080
4105
|
visitAll$1(this, block.children);
|
|
@@ -4083,8 +4108,9 @@ class RecursiveVisitor$1 {
|
|
|
4083
4108
|
visitAll$1(this, block.branches);
|
|
4084
4109
|
}
|
|
4085
4110
|
visitIfBlockBranch(block) {
|
|
4086
|
-
|
|
4087
|
-
block.expressionAlias
|
|
4111
|
+
const blockItems = block.children;
|
|
4112
|
+
block.expressionAlias && blockItems.push(block.expressionAlias);
|
|
4113
|
+
visitAll$1(this, blockItems);
|
|
4088
4114
|
}
|
|
4089
4115
|
visitContent(content) { }
|
|
4090
4116
|
visitVariable(variable) { }
|
|
@@ -4096,6 +4122,7 @@ class RecursiveVisitor$1 {
|
|
|
4096
4122
|
visitBoundText(text) { }
|
|
4097
4123
|
visitIcu(icu) { }
|
|
4098
4124
|
visitDeferredTrigger(trigger) { }
|
|
4125
|
+
visitUnknownBlock(block) { }
|
|
4099
4126
|
}
|
|
4100
4127
|
function visitAll$1(visitor, nodes) {
|
|
4101
4128
|
const result = [];
|
|
@@ -4931,7 +4958,13 @@ class DefinitionMap {
|
|
|
4931
4958
|
}
|
|
4932
4959
|
set(key, value) {
|
|
4933
4960
|
if (value) {
|
|
4934
|
-
this.values.
|
|
4961
|
+
const existing = this.values.find(value => value.key === key);
|
|
4962
|
+
if (existing) {
|
|
4963
|
+
existing.value = value;
|
|
4964
|
+
}
|
|
4965
|
+
else {
|
|
4966
|
+
this.values.push({ key: key, value, quoted: false });
|
|
4967
|
+
}
|
|
4935
4968
|
}
|
|
4936
4969
|
}
|
|
4937
4970
|
toLiteralMap() {
|
|
@@ -5074,10 +5107,7 @@ function compileInjectable(meta, resolveForwardRefs) {
|
|
|
5074
5107
|
});
|
|
5075
5108
|
}
|
|
5076
5109
|
else {
|
|
5077
|
-
result = {
|
|
5078
|
-
statements: [],
|
|
5079
|
-
expression: fn([], [new ReturnStatement(meta.useFactory.callFn([]))])
|
|
5080
|
-
};
|
|
5110
|
+
result = { statements: [], expression: arrowFn([], meta.useFactory.callFn([])) };
|
|
5081
5111
|
}
|
|
5082
5112
|
}
|
|
5083
5113
|
else if (meta.useValue !== undefined) {
|
|
@@ -5146,7 +5176,7 @@ function delegateToFactory(type, useType, unwrapForwardRefs) {
|
|
|
5146
5176
|
return createFactoryFunction(unwrappedType);
|
|
5147
5177
|
}
|
|
5148
5178
|
function createFactoryFunction(type) {
|
|
5149
|
-
return
|
|
5179
|
+
return arrowFn([new FnParam('t', DYNAMIC_TYPE)], type.prop('ɵfac').callFn([variable('t')]));
|
|
5150
5180
|
}
|
|
5151
5181
|
|
|
5152
5182
|
const UNUSABLE_INTERPOLATION_REGEXPS = [
|
|
@@ -8759,38 +8789,58 @@ var OpKind;
|
|
|
8759
8789
|
* An attribute that has been extracted for inclusion in the consts array.
|
|
8760
8790
|
*/
|
|
8761
8791
|
OpKind[OpKind["ExtractedAttribute"] = 25] = "ExtractedAttribute";
|
|
8792
|
+
/**
|
|
8793
|
+
* An operation that configures a `@defer` block.
|
|
8794
|
+
*/
|
|
8795
|
+
OpKind[OpKind["Defer"] = 26] = "Defer";
|
|
8796
|
+
/**
|
|
8797
|
+
* An IR operation that provides secondary templates of a `@defer` block.
|
|
8798
|
+
*/
|
|
8799
|
+
OpKind[OpKind["DeferSecondaryBlock"] = 27] = "DeferSecondaryBlock";
|
|
8800
|
+
/**
|
|
8801
|
+
* An operation that controls when a `@defer` loads.
|
|
8802
|
+
*/
|
|
8803
|
+
OpKind[OpKind["DeferOn"] = 28] = "DeferOn";
|
|
8762
8804
|
/**
|
|
8763
8805
|
* An i18n message that has been extracted for inclusion in the consts array.
|
|
8764
8806
|
*/
|
|
8765
|
-
OpKind[OpKind["ExtractedMessage"] =
|
|
8807
|
+
OpKind[OpKind["ExtractedMessage"] = 29] = "ExtractedMessage";
|
|
8766
8808
|
/**
|
|
8767
8809
|
* A host binding property.
|
|
8768
8810
|
*/
|
|
8769
|
-
OpKind[OpKind["HostProperty"] =
|
|
8811
|
+
OpKind[OpKind["HostProperty"] = 30] = "HostProperty";
|
|
8770
8812
|
/**
|
|
8771
8813
|
* A namespace change, which causes the subsequent elements to be processed as either HTML or SVG.
|
|
8772
8814
|
*/
|
|
8773
|
-
OpKind[OpKind["Namespace"] =
|
|
8815
|
+
OpKind[OpKind["Namespace"] = 31] = "Namespace";
|
|
8774
8816
|
/**
|
|
8775
8817
|
* Configure a content projeciton definition for the view.
|
|
8776
8818
|
*/
|
|
8777
|
-
OpKind[OpKind["ProjectionDef"] =
|
|
8819
|
+
OpKind[OpKind["ProjectionDef"] = 32] = "ProjectionDef";
|
|
8778
8820
|
/**
|
|
8779
8821
|
* Create a content projection slot.
|
|
8780
8822
|
*/
|
|
8781
|
-
OpKind[OpKind["Projection"] =
|
|
8823
|
+
OpKind[OpKind["Projection"] = 33] = "Projection";
|
|
8782
8824
|
/**
|
|
8783
8825
|
* The start of an i18n block.
|
|
8784
8826
|
*/
|
|
8785
|
-
OpKind[OpKind["I18nStart"] =
|
|
8827
|
+
OpKind[OpKind["I18nStart"] = 34] = "I18nStart";
|
|
8786
8828
|
/**
|
|
8787
8829
|
* A self-closing i18n on a single element.
|
|
8788
8830
|
*/
|
|
8789
|
-
OpKind[OpKind["I18n"] =
|
|
8831
|
+
OpKind[OpKind["I18n"] = 35] = "I18n";
|
|
8790
8832
|
/**
|
|
8791
8833
|
* The end of an i18n block.
|
|
8792
8834
|
*/
|
|
8793
|
-
OpKind[OpKind["I18nEnd"] =
|
|
8835
|
+
OpKind[OpKind["I18nEnd"] = 36] = "I18nEnd";
|
|
8836
|
+
/**
|
|
8837
|
+
* An expression in an i18n message.
|
|
8838
|
+
*/
|
|
8839
|
+
OpKind[OpKind["I18nExpression"] = 37] = "I18nExpression";
|
|
8840
|
+
/**
|
|
8841
|
+
* An instruction that applies a set of i18n expressions.
|
|
8842
|
+
*/
|
|
8843
|
+
OpKind[OpKind["I18nApply"] = 38] = "I18nApply";
|
|
8794
8844
|
})(OpKind || (OpKind = {}));
|
|
8795
8845
|
/**
|
|
8796
8846
|
* Distinguishes different kinds of IR expressions.
|
|
@@ -8881,6 +8931,10 @@ var ExpressionKind;
|
|
|
8881
8931
|
* An expression that will cause a literal slot index to be emitted.
|
|
8882
8932
|
*/
|
|
8883
8933
|
ExpressionKind[ExpressionKind["SlotLiteralExpr"] = 20] = "SlotLiteralExpr";
|
|
8934
|
+
/**
|
|
8935
|
+
* A test expression for a conditional op.
|
|
8936
|
+
*/
|
|
8937
|
+
ExpressionKind[ExpressionKind["ConditionalCase"] = 21] = "ConditionalCase";
|
|
8884
8938
|
})(ExpressionKind || (ExpressionKind = {}));
|
|
8885
8939
|
/**
|
|
8886
8940
|
* Distinguishes between different kinds of `SemanticVariable`s.
|
|
@@ -8922,6 +8976,15 @@ var SanitizerFn;
|
|
|
8922
8976
|
SanitizerFn[SanitizerFn["ResourceUrl"] = 4] = "ResourceUrl";
|
|
8923
8977
|
SanitizerFn[SanitizerFn["IframeAttribute"] = 5] = "IframeAttribute";
|
|
8924
8978
|
})(SanitizerFn || (SanitizerFn = {}));
|
|
8979
|
+
/**
|
|
8980
|
+
* Enumeration of the different kinds of `@defer` secondary blocks.
|
|
8981
|
+
*/
|
|
8982
|
+
var DeferSecondaryKind;
|
|
8983
|
+
(function (DeferSecondaryKind) {
|
|
8984
|
+
DeferSecondaryKind[DeferSecondaryKind["Loading"] = 0] = "Loading";
|
|
8985
|
+
DeferSecondaryKind[DeferSecondaryKind["Placeholder"] = 1] = "Placeholder";
|
|
8986
|
+
DeferSecondaryKind[DeferSecondaryKind["Error"] = 2] = "Error";
|
|
8987
|
+
})(DeferSecondaryKind || (DeferSecondaryKind = {}));
|
|
8925
8988
|
/**
|
|
8926
8989
|
* Enumeration of the types of attributes which can be applied to an element.
|
|
8927
8990
|
*/
|
|
@@ -8977,6 +9040,10 @@ const ConsumesVarsTrait = Symbol('ConsumesVars');
|
|
|
8977
9040
|
* Marker symbol for `UsesVarOffset` trait.
|
|
8978
9041
|
*/
|
|
8979
9042
|
const UsesVarOffset = Symbol('UsesVarOffset');
|
|
9043
|
+
/**
|
|
9044
|
+
* Marker symbol for `HasConst` trait.
|
|
9045
|
+
*/
|
|
9046
|
+
const HasConst = Symbol('HasConst');
|
|
8980
9047
|
/**
|
|
8981
9048
|
* Default values for most `ConsumesSlotOpTrait` fields (used with the spread operator to initialize
|
|
8982
9049
|
* implementors of the trait).
|
|
@@ -8992,7 +9059,7 @@ const TRAIT_CONSUMES_SLOT = {
|
|
|
8992
9059
|
*/
|
|
8993
9060
|
const TRAIT_USES_SLOT_INDEX = {
|
|
8994
9061
|
[UsesSlotIndex]: true,
|
|
8995
|
-
|
|
9062
|
+
targetSlot: null,
|
|
8996
9063
|
};
|
|
8997
9064
|
/**
|
|
8998
9065
|
* Default values for most `DependsOnSlotContextOpTrait` fields (used with the spread operator to
|
|
@@ -9016,6 +9083,14 @@ const TRAIT_USES_VAR_OFFSET = {
|
|
|
9016
9083
|
[UsesVarOffset]: true,
|
|
9017
9084
|
varOffset: null,
|
|
9018
9085
|
};
|
|
9086
|
+
/**
|
|
9087
|
+
* Default values for `HasConst` fields (used with the spread operator to initialize
|
|
9088
|
+
* implementors of this trait).
|
|
9089
|
+
*/
|
|
9090
|
+
const TRAIT_HAS_CONST = {
|
|
9091
|
+
[HasConst]: true,
|
|
9092
|
+
constIndex: null,
|
|
9093
|
+
};
|
|
9019
9094
|
/**
|
|
9020
9095
|
* Test whether an operation implements `ConsumesSlotOpTrait`.
|
|
9021
9096
|
*/
|
|
@@ -9040,6 +9115,9 @@ function hasUsesVarOffsetTrait(expr) {
|
|
|
9040
9115
|
function hasUsesSlotIndexTrait(value) {
|
|
9041
9116
|
return value[UsesSlotIndex] === true;
|
|
9042
9117
|
}
|
|
9118
|
+
function hasConstTrait(value) {
|
|
9119
|
+
return value[HasConst] === true;
|
|
9120
|
+
}
|
|
9043
9121
|
|
|
9044
9122
|
/**
|
|
9045
9123
|
* Create a `StatementOp`.
|
|
@@ -9078,11 +9156,12 @@ const NEW_OP = {
|
|
|
9078
9156
|
/**
|
|
9079
9157
|
* Create an `InterpolationTextOp`.
|
|
9080
9158
|
*/
|
|
9081
|
-
function createInterpolateTextOp(xref, interpolation, sourceSpan) {
|
|
9159
|
+
function createInterpolateTextOp(xref, interpolation, i18nPlaceholders, sourceSpan) {
|
|
9082
9160
|
return {
|
|
9083
9161
|
kind: OpKind.InterpolateText,
|
|
9084
9162
|
target: xref,
|
|
9085
9163
|
interpolation,
|
|
9164
|
+
i18nPlaceholders,
|
|
9086
9165
|
sourceSpan,
|
|
9087
9166
|
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9088
9167
|
...TRAIT_CONSUMES_VARS,
|
|
@@ -9220,17 +9299,47 @@ function createAdvanceOp(delta, sourceSpan) {
|
|
|
9220
9299
|
/**
|
|
9221
9300
|
* Create a conditional op, which will display an embedded view according to a condtion.
|
|
9222
9301
|
*/
|
|
9223
|
-
function createConditionalOp(target, test, sourceSpan) {
|
|
9302
|
+
function createConditionalOp(target, test, conditions, sourceSpan) {
|
|
9224
9303
|
return {
|
|
9225
9304
|
kind: OpKind.Conditional,
|
|
9226
9305
|
target,
|
|
9227
9306
|
test,
|
|
9228
|
-
conditions
|
|
9307
|
+
conditions,
|
|
9229
9308
|
processed: null,
|
|
9230
9309
|
sourceSpan,
|
|
9310
|
+
contextValue: null,
|
|
9231
9311
|
...NEW_OP,
|
|
9232
9312
|
...TRAIT_USES_SLOT_INDEX,
|
|
9233
9313
|
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9314
|
+
...TRAIT_CONSUMES_VARS,
|
|
9315
|
+
};
|
|
9316
|
+
}
|
|
9317
|
+
/**
|
|
9318
|
+
* Create an i18n expression op.
|
|
9319
|
+
*/
|
|
9320
|
+
function createI18nExpressionOp(owner, expression, i18nPlaceholder, sourceSpan) {
|
|
9321
|
+
return {
|
|
9322
|
+
kind: OpKind.I18nExpression,
|
|
9323
|
+
owner,
|
|
9324
|
+
target: owner,
|
|
9325
|
+
expression,
|
|
9326
|
+
i18nPlaceholder,
|
|
9327
|
+
sourceSpan,
|
|
9328
|
+
...NEW_OP,
|
|
9329
|
+
...TRAIT_CONSUMES_VARS,
|
|
9330
|
+
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9331
|
+
};
|
|
9332
|
+
}
|
|
9333
|
+
/**
|
|
9334
|
+
* Creates an op to apply i18n expression ops.
|
|
9335
|
+
*/
|
|
9336
|
+
function createI18nApplyOp(target, sourceSpan) {
|
|
9337
|
+
return {
|
|
9338
|
+
kind: OpKind.I18nApply,
|
|
9339
|
+
target,
|
|
9340
|
+
sourceSpan,
|
|
9341
|
+
...NEW_OP,
|
|
9342
|
+
...TRAIT_USES_SLOT_INDEX,
|
|
9234
9343
|
};
|
|
9235
9344
|
}
|
|
9236
9345
|
|
|
@@ -9281,7 +9390,7 @@ class ReferenceExpr extends ExpressionBase {
|
|
|
9281
9390
|
this.offset = offset;
|
|
9282
9391
|
this.kind = ExpressionKind.Reference;
|
|
9283
9392
|
this[_a] = true;
|
|
9284
|
-
this.
|
|
9393
|
+
this.targetSlot = null;
|
|
9285
9394
|
}
|
|
9286
9395
|
visitExpression() { }
|
|
9287
9396
|
isEquivalent(e) {
|
|
@@ -9293,7 +9402,7 @@ class ReferenceExpr extends ExpressionBase {
|
|
|
9293
9402
|
transformInternalExpressions() { }
|
|
9294
9403
|
clone() {
|
|
9295
9404
|
const expr = new ReferenceExpr(this.target, this.offset);
|
|
9296
|
-
expr.
|
|
9405
|
+
expr.targetSlot = this.targetSlot;
|
|
9297
9406
|
return expr;
|
|
9298
9407
|
}
|
|
9299
9408
|
}
|
|
@@ -9530,7 +9639,7 @@ class PipeBindingExpr extends ExpressionBase {
|
|
|
9530
9639
|
this[_d] = true;
|
|
9531
9640
|
this[_e] = true;
|
|
9532
9641
|
this[_f] = true;
|
|
9533
|
-
this.
|
|
9642
|
+
this.targetSlot = null;
|
|
9534
9643
|
this.varOffset = null;
|
|
9535
9644
|
}
|
|
9536
9645
|
visitExpression(visitor, context) {
|
|
@@ -9551,7 +9660,7 @@ class PipeBindingExpr extends ExpressionBase {
|
|
|
9551
9660
|
}
|
|
9552
9661
|
clone() {
|
|
9553
9662
|
const r = new PipeBindingExpr(this.target, this.name, this.args.map(a => a.clone()));
|
|
9554
|
-
r.
|
|
9663
|
+
r.targetSlot = this.targetSlot;
|
|
9555
9664
|
r.varOffset = this.varOffset;
|
|
9556
9665
|
return r;
|
|
9557
9666
|
}
|
|
@@ -9568,7 +9677,7 @@ class PipeBindingVariadicExpr extends ExpressionBase {
|
|
|
9568
9677
|
this[_g] = true;
|
|
9569
9678
|
this[_h] = true;
|
|
9570
9679
|
this[_j] = true;
|
|
9571
|
-
this.
|
|
9680
|
+
this.targetSlot = null;
|
|
9572
9681
|
this.varOffset = null;
|
|
9573
9682
|
}
|
|
9574
9683
|
visitExpression(visitor, context) {
|
|
@@ -9585,7 +9694,7 @@ class PipeBindingVariadicExpr extends ExpressionBase {
|
|
|
9585
9694
|
}
|
|
9586
9695
|
clone() {
|
|
9587
9696
|
const r = new PipeBindingVariadicExpr(this.target, this.name, this.args.clone(), this.numArgs);
|
|
9588
|
-
r.
|
|
9697
|
+
r.targetSlot = this.targetSlot;
|
|
9589
9698
|
r.varOffset = this.varOffset;
|
|
9590
9699
|
return r;
|
|
9591
9700
|
}
|
|
@@ -9785,20 +9894,56 @@ class SlotLiteralExpr extends ExpressionBase {
|
|
|
9785
9894
|
this.target = target;
|
|
9786
9895
|
this.kind = ExpressionKind.SlotLiteralExpr;
|
|
9787
9896
|
this[_k] = true;
|
|
9788
|
-
this.
|
|
9897
|
+
this.targetSlot = null;
|
|
9789
9898
|
}
|
|
9790
9899
|
visitExpression(visitor, context) { }
|
|
9791
9900
|
isEquivalent(e) {
|
|
9792
|
-
return e instanceof SlotLiteralExpr && e.target === this.target &&
|
|
9901
|
+
return e instanceof SlotLiteralExpr && e.target === this.target &&
|
|
9902
|
+
e.targetSlot === this.targetSlot;
|
|
9793
9903
|
}
|
|
9794
9904
|
isConstant() {
|
|
9795
9905
|
return true;
|
|
9796
9906
|
}
|
|
9797
9907
|
clone() {
|
|
9798
|
-
|
|
9908
|
+
const copy = new SlotLiteralExpr(this.target);
|
|
9909
|
+
copy.targetSlot = this.targetSlot;
|
|
9910
|
+
return copy;
|
|
9799
9911
|
}
|
|
9800
9912
|
transformInternalExpressions() { }
|
|
9801
9913
|
}
|
|
9914
|
+
class ConditionalCaseExpr extends ExpressionBase {
|
|
9915
|
+
/**
|
|
9916
|
+
* Create an expression for one branch of a conditional.
|
|
9917
|
+
* @param expr The expression to be tested for this case. Might be null, as in an `else` case.
|
|
9918
|
+
* @param target The Xref of the view to be displayed if this condition is true.
|
|
9919
|
+
*/
|
|
9920
|
+
constructor(expr, target, alias = null) {
|
|
9921
|
+
super();
|
|
9922
|
+
this.expr = expr;
|
|
9923
|
+
this.target = target;
|
|
9924
|
+
this.alias = alias;
|
|
9925
|
+
this.kind = ExpressionKind.ConditionalCase;
|
|
9926
|
+
}
|
|
9927
|
+
visitExpression(visitor, context) {
|
|
9928
|
+
if (this.expr !== null) {
|
|
9929
|
+
this.expr.visitExpression(visitor, context);
|
|
9930
|
+
}
|
|
9931
|
+
}
|
|
9932
|
+
isEquivalent(e) {
|
|
9933
|
+
return e instanceof ConditionalCaseExpr && e.expr === this.expr;
|
|
9934
|
+
}
|
|
9935
|
+
isConstant() {
|
|
9936
|
+
return true;
|
|
9937
|
+
}
|
|
9938
|
+
clone() {
|
|
9939
|
+
return new ConditionalCaseExpr(this.expr, this.target);
|
|
9940
|
+
}
|
|
9941
|
+
transformInternalExpressions(transform, flags) {
|
|
9942
|
+
if (this.expr !== null) {
|
|
9943
|
+
this.expr = transformExpressionsInExpression(this.expr, transform, flags);
|
|
9944
|
+
}
|
|
9945
|
+
}
|
|
9946
|
+
}
|
|
9802
9947
|
/**
|
|
9803
9948
|
* Visits all `Expression`s in the AST of `op` with the `visitor` function.
|
|
9804
9949
|
*/
|
|
@@ -9851,6 +9996,9 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
9851
9996
|
op.sanitizer =
|
|
9852
9997
|
op.sanitizer && transformExpressionsInExpression(op.sanitizer, transform, flags);
|
|
9853
9998
|
break;
|
|
9999
|
+
case OpKind.I18nExpression:
|
|
10000
|
+
op.expression = transformExpressionsInExpression(op.expression, transform, flags);
|
|
10001
|
+
break;
|
|
9854
10002
|
case OpKind.InterpolateText:
|
|
9855
10003
|
transformExpressionsInInterpolation(op.interpolation, transform, flags);
|
|
9856
10004
|
break;
|
|
@@ -9862,15 +10010,18 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
9862
10010
|
break;
|
|
9863
10011
|
case OpKind.Conditional:
|
|
9864
10012
|
for (const condition of op.conditions) {
|
|
9865
|
-
if (condition
|
|
10013
|
+
if (condition.expr === null) {
|
|
9866
10014
|
// This is a default case.
|
|
9867
10015
|
continue;
|
|
9868
10016
|
}
|
|
9869
|
-
condition
|
|
10017
|
+
condition.expr = transformExpressionsInExpression(condition.expr, transform, flags);
|
|
9870
10018
|
}
|
|
9871
10019
|
if (op.processed !== null) {
|
|
9872
10020
|
op.processed = transformExpressionsInExpression(op.processed, transform, flags);
|
|
9873
10021
|
}
|
|
10022
|
+
if (op.contextValue !== null) {
|
|
10023
|
+
op.contextValue = transformExpressionsInExpression(op.contextValue, transform, flags);
|
|
10024
|
+
}
|
|
9874
10025
|
break;
|
|
9875
10026
|
case OpKind.Listener:
|
|
9876
10027
|
for (const innerOp of op.handlerOps) {
|
|
@@ -9887,18 +10038,20 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
9887
10038
|
transformExpressionsInStatement(statement, transform, flags);
|
|
9888
10039
|
}
|
|
9889
10040
|
break;
|
|
10041
|
+
case OpKind.I18n:
|
|
9890
10042
|
case OpKind.I18nStart:
|
|
9891
|
-
for (const placeholder
|
|
9892
|
-
op.
|
|
9893
|
-
transformExpressionsInExpression(op.tagNameParams[placeholder], transform, flags);
|
|
10043
|
+
for (const [placeholder, expression] of op.params) {
|
|
10044
|
+
op.params.set(placeholder, transformExpressionsInExpression(expression, transform, flags));
|
|
9894
10045
|
}
|
|
9895
10046
|
break;
|
|
10047
|
+
case OpKind.Defer:
|
|
10048
|
+
case OpKind.DeferSecondaryBlock:
|
|
10049
|
+
case OpKind.DeferOn:
|
|
9896
10050
|
case OpKind.Projection:
|
|
9897
10051
|
case OpKind.ProjectionDef:
|
|
9898
10052
|
case OpKind.Element:
|
|
9899
10053
|
case OpKind.ElementStart:
|
|
9900
10054
|
case OpKind.ElementEnd:
|
|
9901
|
-
case OpKind.I18n:
|
|
9902
10055
|
case OpKind.I18nEnd:
|
|
9903
10056
|
case OpKind.Container:
|
|
9904
10057
|
case OpKind.ContainerStart:
|
|
@@ -9910,6 +10063,7 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
9910
10063
|
case OpKind.Pipe:
|
|
9911
10064
|
case OpKind.Advance:
|
|
9912
10065
|
case OpKind.Namespace:
|
|
10066
|
+
case OpKind.I18nApply:
|
|
9913
10067
|
// These operations contain no expressions.
|
|
9914
10068
|
break;
|
|
9915
10069
|
default:
|
|
@@ -10190,7 +10344,7 @@ class OpList {
|
|
|
10190
10344
|
// Replace `oldOp` with the chain `first` -> `last`.
|
|
10191
10345
|
if (oldPrev !== null) {
|
|
10192
10346
|
oldPrev.next = first;
|
|
10193
|
-
first.prev =
|
|
10347
|
+
first.prev = oldPrev;
|
|
10194
10348
|
}
|
|
10195
10349
|
if (oldNext !== null) {
|
|
10196
10350
|
oldNext.prev = last;
|
|
@@ -10297,7 +10451,7 @@ function isElementOrContainerOp(op) {
|
|
|
10297
10451
|
/**
|
|
10298
10452
|
* Create an `ElementStartOp`.
|
|
10299
10453
|
*/
|
|
10300
|
-
function createElementStartOp(tag, xref, namespace,
|
|
10454
|
+
function createElementStartOp(tag, xref, namespace, i18nPlaceholder, sourceSpan) {
|
|
10301
10455
|
return {
|
|
10302
10456
|
kind: OpKind.ElementStart,
|
|
10303
10457
|
xref,
|
|
@@ -10306,7 +10460,7 @@ function createElementStartOp(tag, xref, namespace, i18n, sourceSpan) {
|
|
|
10306
10460
|
localRefs: [],
|
|
10307
10461
|
nonBindable: false,
|
|
10308
10462
|
namespace,
|
|
10309
|
-
|
|
10463
|
+
i18nPlaceholder,
|
|
10310
10464
|
sourceSpan,
|
|
10311
10465
|
...TRAIT_CONSUMES_SLOT,
|
|
10312
10466
|
...NEW_OP,
|
|
@@ -10315,19 +10469,19 @@ function createElementStartOp(tag, xref, namespace, i18n, sourceSpan) {
|
|
|
10315
10469
|
/**
|
|
10316
10470
|
* Create a `TemplateOp`.
|
|
10317
10471
|
*/
|
|
10318
|
-
function createTemplateOp(xref, tag, namespace,
|
|
10472
|
+
function createTemplateOp(xref, tag, namespace, generatedInBlock, i18nPlaceholder, sourceSpan) {
|
|
10319
10473
|
return {
|
|
10320
10474
|
kind: OpKind.Template,
|
|
10321
10475
|
xref,
|
|
10322
10476
|
attributes: null,
|
|
10323
10477
|
tag,
|
|
10324
|
-
|
|
10478
|
+
block: generatedInBlock,
|
|
10325
10479
|
decls: null,
|
|
10326
10480
|
vars: null,
|
|
10327
10481
|
localRefs: [],
|
|
10328
10482
|
nonBindable: false,
|
|
10329
10483
|
namespace,
|
|
10330
|
-
|
|
10484
|
+
i18nPlaceholder,
|
|
10331
10485
|
sourceSpan,
|
|
10332
10486
|
...TRAIT_CONSUMES_SLOT,
|
|
10333
10487
|
...NEW_OP,
|
|
@@ -10432,11 +10586,9 @@ function createProjectionOp(xref, selector) {
|
|
|
10432
10586
|
attributes: null,
|
|
10433
10587
|
localRefs: [],
|
|
10434
10588
|
nonBindable: false,
|
|
10435
|
-
i18n: undefined,
|
|
10436
10589
|
sourceSpan: null,
|
|
10437
10590
|
...NEW_OP,
|
|
10438
10591
|
...TRAIT_CONSUMES_SLOT,
|
|
10439
|
-
...TRAIT_USES_SLOT_INDEX,
|
|
10440
10592
|
};
|
|
10441
10593
|
}
|
|
10442
10594
|
/**
|
|
@@ -10452,6 +10604,42 @@ function createExtractedAttributeOp(target, bindingKind, name, expression) {
|
|
|
10452
10604
|
...NEW_OP,
|
|
10453
10605
|
};
|
|
10454
10606
|
}
|
|
10607
|
+
function createDeferOp(xref, main, sourceSpan) {
|
|
10608
|
+
return {
|
|
10609
|
+
kind: OpKind.Defer,
|
|
10610
|
+
xref,
|
|
10611
|
+
target: main,
|
|
10612
|
+
loading: null,
|
|
10613
|
+
placeholder: null,
|
|
10614
|
+
error: null,
|
|
10615
|
+
sourceSpan,
|
|
10616
|
+
...NEW_OP,
|
|
10617
|
+
...TRAIT_CONSUMES_SLOT,
|
|
10618
|
+
...TRAIT_USES_SLOT_INDEX,
|
|
10619
|
+
};
|
|
10620
|
+
}
|
|
10621
|
+
function createDeferSecondaryOp(deferOp, secondaryView, secondaryBlockKind) {
|
|
10622
|
+
return {
|
|
10623
|
+
kind: OpKind.DeferSecondaryBlock,
|
|
10624
|
+
deferOp,
|
|
10625
|
+
target: secondaryView,
|
|
10626
|
+
secondaryBlockKind,
|
|
10627
|
+
constValue: null,
|
|
10628
|
+
makeExpression: literalOrArrayLiteral$1,
|
|
10629
|
+
...NEW_OP,
|
|
10630
|
+
...TRAIT_USES_SLOT_INDEX,
|
|
10631
|
+
...TRAIT_HAS_CONST,
|
|
10632
|
+
};
|
|
10633
|
+
}
|
|
10634
|
+
function createDeferOnOp(xref, sourceSpan) {
|
|
10635
|
+
return {
|
|
10636
|
+
kind: OpKind.DeferOn,
|
|
10637
|
+
xref,
|
|
10638
|
+
sourceSpan,
|
|
10639
|
+
...NEW_OP,
|
|
10640
|
+
...TRAIT_CONSUMES_SLOT,
|
|
10641
|
+
};
|
|
10642
|
+
}
|
|
10455
10643
|
/**
|
|
10456
10644
|
* Create an `ExtractedMessageOp`.
|
|
10457
10645
|
*/
|
|
@@ -10467,13 +10655,15 @@ function createExtractedMessageOp(owner, expression, statements) {
|
|
|
10467
10655
|
/**
|
|
10468
10656
|
* Create an `I18nStartOp`.
|
|
10469
10657
|
*/
|
|
10470
|
-
function createI18nStartOp(xref,
|
|
10658
|
+
function createI18nStartOp(xref, message, root) {
|
|
10471
10659
|
return {
|
|
10472
10660
|
kind: OpKind.I18nStart,
|
|
10473
10661
|
xref,
|
|
10474
|
-
|
|
10475
|
-
|
|
10662
|
+
root: root ?? xref,
|
|
10663
|
+
message,
|
|
10664
|
+
params: new Map(),
|
|
10476
10665
|
messageIndex: null,
|
|
10666
|
+
subTemplateIndex: null,
|
|
10477
10667
|
...NEW_OP,
|
|
10478
10668
|
...TRAIT_CONSUMES_SLOT,
|
|
10479
10669
|
};
|
|
@@ -10488,6 +10678,12 @@ function createI18nEndOp(xref) {
|
|
|
10488
10678
|
...NEW_OP,
|
|
10489
10679
|
};
|
|
10490
10680
|
}
|
|
10681
|
+
function literalOrArrayLiteral$1(value) {
|
|
10682
|
+
if (Array.isArray(value)) {
|
|
10683
|
+
return literalArr(value.map(literalOrArrayLiteral$1));
|
|
10684
|
+
}
|
|
10685
|
+
return literal(value, INFERRED_TYPE);
|
|
10686
|
+
}
|
|
10491
10687
|
|
|
10492
10688
|
function createHostPropertyOp(name, expression, isAnimationTrigger, sourceSpan) {
|
|
10493
10689
|
return {
|
|
@@ -10501,6 +10697,12 @@ function createHostPropertyOp(name, expression, isAnimationTrigger, sourceSpan)
|
|
|
10501
10697
|
};
|
|
10502
10698
|
}
|
|
10503
10699
|
|
|
10700
|
+
/**
|
|
10701
|
+
* When referenced in the template's context parameters, this indicates a reference to the entire
|
|
10702
|
+
* context object, rather than a specific parameter.
|
|
10703
|
+
*/
|
|
10704
|
+
const CTX_REF = 'CTX_REF_MARKER';
|
|
10705
|
+
|
|
10504
10706
|
var CompilationJobKind;
|
|
10505
10707
|
(function (CompilationJobKind) {
|
|
10506
10708
|
CompilationJobKind[CompilationJobKind["Tmpl"] = 0] = "Tmpl";
|
|
@@ -10688,10 +10890,16 @@ function phaseVarCounting(job) {
|
|
|
10688
10890
|
// First, count the vars used in each view, and update the view-level counter.
|
|
10689
10891
|
for (const unit of job.units) {
|
|
10690
10892
|
let varCount = 0;
|
|
10893
|
+
// Count variables on top-level ops first. Don't explore nested expressions just yet.
|
|
10691
10894
|
for (const op of unit.ops()) {
|
|
10692
10895
|
if (hasConsumesVarsTrait(op)) {
|
|
10693
10896
|
varCount += varsUsedByOp(op);
|
|
10694
10897
|
}
|
|
10898
|
+
}
|
|
10899
|
+
// Count variables on expressions inside ops. We do this later because some of these expressions
|
|
10900
|
+
// might be conditional (e.g. `pipeBinding` inside of a ternary), and we don't want to interfere
|
|
10901
|
+
// with indices for top-level binding slots (e.g. `property`).
|
|
10902
|
+
for (const op of unit.ops()) {
|
|
10695
10903
|
visitExpressionsInOp(op, expr => {
|
|
10696
10904
|
if (!isIrExpression(expr)) {
|
|
10697
10905
|
return;
|
|
@@ -10752,6 +10960,9 @@ function varsUsedByOp(op) {
|
|
|
10752
10960
|
case OpKind.InterpolateText:
|
|
10753
10961
|
// `ir.InterpolateTextOp`s use a variable slot for each dynamic expression.
|
|
10754
10962
|
return op.interpolation.expressions.length;
|
|
10963
|
+
case OpKind.I18nExpression:
|
|
10964
|
+
case OpKind.Conditional:
|
|
10965
|
+
return 1;
|
|
10755
10966
|
default:
|
|
10756
10967
|
throw new Error(`Unhandled op: ${OpKind[op.kind]}`);
|
|
10757
10968
|
}
|
|
@@ -10823,6 +11034,60 @@ function removeAnys(e) {
|
|
|
10823
11034
|
return e;
|
|
10824
11035
|
}
|
|
10825
11036
|
|
|
11037
|
+
/**
|
|
11038
|
+
* Adds apply operations after i18n expressions.
|
|
11039
|
+
*/
|
|
11040
|
+
function phaseApplyI18nExpressions(job) {
|
|
11041
|
+
for (const unit of job.units) {
|
|
11042
|
+
for (const op of unit.update) {
|
|
11043
|
+
// Only add apply after expressions that are not followed by more expressions.
|
|
11044
|
+
if (op.kind === OpKind.I18nExpression && needsApplication(op)) {
|
|
11045
|
+
// TODO: what should be the source span for the apply op?
|
|
11046
|
+
OpList.insertAfter(createI18nApplyOp(op.owner, null), op);
|
|
11047
|
+
}
|
|
11048
|
+
}
|
|
11049
|
+
}
|
|
11050
|
+
}
|
|
11051
|
+
/**
|
|
11052
|
+
* Checks whether the given expression op needs to be followed with an apply op.
|
|
11053
|
+
*/
|
|
11054
|
+
function needsApplication(op) {
|
|
11055
|
+
// If the next op is not another expression, we need to apply.
|
|
11056
|
+
if (op.next?.kind !== OpKind.I18nExpression) {
|
|
11057
|
+
return true;
|
|
11058
|
+
}
|
|
11059
|
+
// If the next op is an expression targeting a different i18n block, we need to apply.
|
|
11060
|
+
if (op.next.owner !== op.owner) {
|
|
11061
|
+
return true;
|
|
11062
|
+
}
|
|
11063
|
+
return false;
|
|
11064
|
+
}
|
|
11065
|
+
|
|
11066
|
+
/**
|
|
11067
|
+
* Updates i18n expression ops to depend on the last slot in their owning i18n block.
|
|
11068
|
+
*/
|
|
11069
|
+
function phaseAssignI18nSlotDependencies(job) {
|
|
11070
|
+
const i18nLastSlotConsumers = new Map();
|
|
11071
|
+
let lastSlotConsumer = null;
|
|
11072
|
+
for (const unit of job.units) {
|
|
11073
|
+
// Record the last consumed slot before each i18n end instruction.
|
|
11074
|
+
for (const op of unit.create) {
|
|
11075
|
+
if (op.kind === OpKind.I18nEnd) {
|
|
11076
|
+
i18nLastSlotConsumers.set(op.xref, lastSlotConsumer);
|
|
11077
|
+
}
|
|
11078
|
+
if (hasConsumesSlotTrait(op)) {
|
|
11079
|
+
lastSlotConsumer = op.xref;
|
|
11080
|
+
}
|
|
11081
|
+
}
|
|
11082
|
+
// Assign i18n expressions to target the last slot in its owning block.
|
|
11083
|
+
for (const op of unit.update) {
|
|
11084
|
+
if (op.kind === OpKind.I18nExpression) {
|
|
11085
|
+
op.target = i18nLastSlotConsumers.get(op.owner);
|
|
11086
|
+
}
|
|
11087
|
+
}
|
|
11088
|
+
}
|
|
11089
|
+
}
|
|
11090
|
+
|
|
10826
11091
|
/**
|
|
10827
11092
|
* Gets a map of all elements in the given view by their xref id.
|
|
10828
11093
|
*/
|
|
@@ -10984,14 +11249,20 @@ function phaseBindingSpecialization(job) {
|
|
|
10984
11249
|
}
|
|
10985
11250
|
|
|
10986
11251
|
const CHAINABLE = new Set([
|
|
10987
|
-
Identifiers.
|
|
10988
|
-
Identifiers.
|
|
11252
|
+
Identifiers.attribute,
|
|
11253
|
+
Identifiers.classProp,
|
|
10989
11254
|
Identifiers.element,
|
|
10990
|
-
Identifiers.
|
|
11255
|
+
Identifiers.elementContainer,
|
|
11256
|
+
Identifiers.elementContainerEnd,
|
|
11257
|
+
Identifiers.elementContainerStart,
|
|
11258
|
+
Identifiers.elementEnd,
|
|
11259
|
+
Identifiers.elementStart,
|
|
10991
11260
|
Identifiers.hostProperty,
|
|
10992
|
-
Identifiers.
|
|
11261
|
+
Identifiers.i18nExp,
|
|
11262
|
+
Identifiers.listener,
|
|
11263
|
+
Identifiers.listener,
|
|
11264
|
+
Identifiers.property,
|
|
10993
11265
|
Identifiers.styleProp,
|
|
10994
|
-
Identifiers.attribute,
|
|
10995
11266
|
Identifiers.stylePropInterpolate1,
|
|
10996
11267
|
Identifiers.stylePropInterpolate2,
|
|
10997
11268
|
Identifiers.stylePropInterpolate3,
|
|
@@ -11001,13 +11272,8 @@ const CHAINABLE = new Set([
|
|
|
11001
11272
|
Identifiers.stylePropInterpolate7,
|
|
11002
11273
|
Identifiers.stylePropInterpolate8,
|
|
11003
11274
|
Identifiers.stylePropInterpolateV,
|
|
11004
|
-
Identifiers.classProp,
|
|
11005
|
-
Identifiers.listener,
|
|
11006
|
-
Identifiers.elementContainerStart,
|
|
11007
|
-
Identifiers.elementContainerEnd,
|
|
11008
|
-
Identifiers.elementContainer,
|
|
11009
|
-
Identifiers.listener,
|
|
11010
11275
|
Identifiers.syntheticHostListener,
|
|
11276
|
+
Identifiers.syntheticHostProperty,
|
|
11011
11277
|
Identifiers.templateCreate,
|
|
11012
11278
|
]);
|
|
11013
11279
|
/**
|
|
@@ -11084,9 +11350,9 @@ function phaseConditionals(job) {
|
|
|
11084
11350
|
}
|
|
11085
11351
|
let test;
|
|
11086
11352
|
// Any case with a `null` condition is `default`. If one exists, default to it instead.
|
|
11087
|
-
const defaultCase = op.conditions.findIndex((
|
|
11353
|
+
const defaultCase = op.conditions.findIndex((cond) => cond.expr === null);
|
|
11088
11354
|
if (defaultCase >= 0) {
|
|
11089
|
-
const
|
|
11355
|
+
const xref = op.conditions.splice(defaultCase, 1)[0].target;
|
|
11090
11356
|
test = new SlotLiteralExpr(xref);
|
|
11091
11357
|
}
|
|
11092
11358
|
else {
|
|
@@ -11094,13 +11360,26 @@ function phaseConditionals(job) {
|
|
|
11094
11360
|
test = literal(-1);
|
|
11095
11361
|
}
|
|
11096
11362
|
// Switch expressions assign their main test to a temporary, to avoid re-executing it.
|
|
11097
|
-
let tmp = new AssignTemporaryExpr(op.test, job.allocateXrefId());
|
|
11098
|
-
// For each remaining condition, test whether the temporary satifies the check.
|
|
11363
|
+
let tmp = op.test == null ? null : new AssignTemporaryExpr(op.test, job.allocateXrefId());
|
|
11364
|
+
// For each remaining condition, test whether the temporary satifies the check. (If no temp is
|
|
11365
|
+
// present, just check each expression directly.)
|
|
11099
11366
|
for (let i = op.conditions.length - 1; i >= 0; i--) {
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
11103
|
-
|
|
11367
|
+
let conditionalCase = op.conditions[i];
|
|
11368
|
+
if (conditionalCase.expr === null) {
|
|
11369
|
+
continue;
|
|
11370
|
+
}
|
|
11371
|
+
if (tmp !== null) {
|
|
11372
|
+
const useTmp = i === 0 ? tmp : new ReadTemporaryExpr(tmp.xref);
|
|
11373
|
+
conditionalCase.expr =
|
|
11374
|
+
new BinaryOperatorExpr(BinaryOperator.Identical, useTmp, conditionalCase.expr);
|
|
11375
|
+
}
|
|
11376
|
+
else if (conditionalCase.alias !== null) {
|
|
11377
|
+
const caseExpressionTemporaryXref = job.allocateXrefId();
|
|
11378
|
+
conditionalCase.expr =
|
|
11379
|
+
new AssignTemporaryExpr(conditionalCase.expr, caseExpressionTemporaryXref);
|
|
11380
|
+
op.contextValue = new ReadTemporaryExpr(caseExpressionTemporaryXref);
|
|
11381
|
+
}
|
|
11382
|
+
test = new ConditionalExpr(conditionalCase.expr, new SlotLiteralExpr(conditionalCase.target), test);
|
|
11104
11383
|
}
|
|
11105
11384
|
// Save the resulting aggregate Joost-expression.
|
|
11106
11385
|
op.processed = test;
|
|
@@ -11162,14 +11441,15 @@ const BINARY_OPERATORS = new Map([
|
|
|
11162
11441
|
['||', BinaryOperator.Or],
|
|
11163
11442
|
['+', BinaryOperator.Plus],
|
|
11164
11443
|
]);
|
|
11165
|
-
const NAMESPACES = new Map([['svg', Namespace.SVG], ['math', Namespace.Math]]);
|
|
11166
11444
|
function namespaceForKey(namespacePrefixKey) {
|
|
11445
|
+
const NAMESPACES = new Map([['svg', Namespace.SVG], ['math', Namespace.Math]]);
|
|
11167
11446
|
if (namespacePrefixKey === null) {
|
|
11168
11447
|
return Namespace.HTML;
|
|
11169
11448
|
}
|
|
11170
11449
|
return NAMESPACES.get(namespacePrefixKey) ?? Namespace.HTML;
|
|
11171
11450
|
}
|
|
11172
11451
|
function keyForNamespace(namespace) {
|
|
11452
|
+
const NAMESPACES = new Map([['svg', Namespace.SVG], ['math', Namespace.Math]]);
|
|
11173
11453
|
for (const [k, n] of NAMESPACES.entries()) {
|
|
11174
11454
|
if (n === namespace) {
|
|
11175
11455
|
return k;
|
|
@@ -11345,6 +11625,10 @@ const REPLACEMENTS = new Map([
|
|
|
11345
11625
|
[OpKind.ContainerEnd, [OpKind.ContainerStart, OpKind.Container]],
|
|
11346
11626
|
[OpKind.I18nEnd, [OpKind.I18nStart, OpKind.I18n]],
|
|
11347
11627
|
]);
|
|
11628
|
+
/**
|
|
11629
|
+
* Op kinds that should not prevent merging of start/end ops.
|
|
11630
|
+
*/
|
|
11631
|
+
const IGNORED_OP_KINDS = new Set([OpKind.Pipe]);
|
|
11348
11632
|
/**
|
|
11349
11633
|
* Replace sequences of mergable elements (e.g. `ElementStart` and `ElementEnd`) with a consolidated
|
|
11350
11634
|
* element (e.g. `Element`).
|
|
@@ -11352,15 +11636,22 @@ const REPLACEMENTS = new Map([
|
|
|
11352
11636
|
function phaseEmptyElements(job) {
|
|
11353
11637
|
for (const unit of job.units) {
|
|
11354
11638
|
for (const op of unit.create) {
|
|
11639
|
+
// Find end ops that may be able to be merged.
|
|
11355
11640
|
const opReplacements = REPLACEMENTS.get(op.kind);
|
|
11356
11641
|
if (opReplacements === undefined) {
|
|
11357
11642
|
continue;
|
|
11358
11643
|
}
|
|
11359
11644
|
const [startKind, mergedKind] = opReplacements;
|
|
11360
|
-
|
|
11645
|
+
// Locate the previous (non-ignored) op.
|
|
11646
|
+
let prevOp = op.prev;
|
|
11647
|
+
while (prevOp !== null && IGNORED_OP_KINDS.has(prevOp.kind)) {
|
|
11648
|
+
prevOp = prevOp.prev;
|
|
11649
|
+
}
|
|
11650
|
+
// If the previous op is the corresponding start op, we can megre.
|
|
11651
|
+
if (prevOp !== null && prevOp.kind === startKind) {
|
|
11361
11652
|
// Transmute the start instruction to the merged version. This is safe as they're designed
|
|
11362
11653
|
// to be identical apart from the `kind`.
|
|
11363
|
-
|
|
11654
|
+
prevOp.kind = mergedKind;
|
|
11364
11655
|
// Remove the end instruction.
|
|
11365
11656
|
OpList.remove(op);
|
|
11366
11657
|
}
|
|
@@ -11592,31 +11883,39 @@ function phaseGenerateAdvance(job) {
|
|
|
11592
11883
|
}
|
|
11593
11884
|
|
|
11594
11885
|
/**
|
|
11595
|
-
*
|
|
11886
|
+
* Locate projection slots, populate the each component's `ngContentSelectors` literal field,
|
|
11887
|
+
* populate `project` arguments, and generate the required `projectionDef` instruction for the job's
|
|
11888
|
+
* root view.
|
|
11596
11889
|
*/
|
|
11597
|
-
function
|
|
11890
|
+
function phaseGenerateProjectionDef(job) {
|
|
11891
|
+
// TODO: Why does TemplateDefinitionBuilder force a shared constant?
|
|
11892
|
+
const share = job.compatibility === CompatibilityMode.TemplateDefinitionBuilder;
|
|
11893
|
+
// Collect all selectors from this component, and its nested views. Also, assign each projection a
|
|
11894
|
+
// unique ascending projection slot index.
|
|
11895
|
+
const selectors = [];
|
|
11896
|
+
let projectionSlotIndex = 0;
|
|
11598
11897
|
for (const unit of job.units) {
|
|
11599
|
-
const elements = getElementsByXrefId(unit);
|
|
11600
11898
|
for (const op of unit.create) {
|
|
11601
|
-
|
|
11602
|
-
|
|
11603
|
-
|
|
11604
|
-
if (start.i18n instanceof Message) {
|
|
11605
|
-
const id = job.allocateXrefId();
|
|
11606
|
-
OpList.insertAfter(createI18nStartOp(id, start.i18n), start);
|
|
11607
|
-
OpList.insertBefore(createI18nEndOp(id), op);
|
|
11608
|
-
}
|
|
11609
|
-
break;
|
|
11610
|
-
case OpKind.Template:
|
|
11611
|
-
if (op.i18n !== undefined) {
|
|
11612
|
-
const id = job.allocateXrefId();
|
|
11613
|
-
OpList.insertBefore(createI18nStartOp(id, op.i18n), op);
|
|
11614
|
-
OpList.insertAfter(createI18nEndOp(id), op);
|
|
11615
|
-
}
|
|
11616
|
-
break;
|
|
11899
|
+
if (op.kind === OpKind.Projection) {
|
|
11900
|
+
selectors.push(op.selector);
|
|
11901
|
+
op.projectionSlotIndex = projectionSlotIndex++;
|
|
11617
11902
|
}
|
|
11618
11903
|
}
|
|
11619
11904
|
}
|
|
11905
|
+
if (selectors.length > 0) {
|
|
11906
|
+
// Create the projectionDef array. If we only found a single wildcard selector, then we use the
|
|
11907
|
+
// default behavior with no arguments instead.
|
|
11908
|
+
let defExpr = null;
|
|
11909
|
+
if (selectors.length > 1 || selectors[0] !== '*') {
|
|
11910
|
+
const def = selectors.map(s => s === '*' ? s : parseSelectorToR3Selector(s));
|
|
11911
|
+
defExpr = job.pool.getConstLiteral(literalOrArrayLiteral(def), share);
|
|
11912
|
+
}
|
|
11913
|
+
// Create the ngContentSelectors constant.
|
|
11914
|
+
job.contentSelectors = job.pool.getConstLiteral(literalOrArrayLiteral(selectors), share);
|
|
11915
|
+
// The projection def instruction goes at the beginning of the root view, before any
|
|
11916
|
+
// `projection` instructions.
|
|
11917
|
+
job.root.create.prepend([createProjectionDefOp(defExpr)]);
|
|
11918
|
+
}
|
|
11620
11919
|
}
|
|
11621
11920
|
|
|
11622
11921
|
/**
|
|
@@ -11727,7 +12026,11 @@ function generateVariablesInScopeForView(view, scope) {
|
|
|
11727
12026
|
}
|
|
11728
12027
|
// Add variables for all context variables available in this scope's view.
|
|
11729
12028
|
for (const [name, value] of view.job.views.get(scope.view).contextVariables) {
|
|
11730
|
-
|
|
12029
|
+
const context = new ContextExpr(scope.view);
|
|
12030
|
+
// We either read the context, or, if the variable is CTX_REF, use the context directly.
|
|
12031
|
+
const variable = value === CTX_REF ? context : new ReadPropExpr(context, value);
|
|
12032
|
+
// Add the variable declaration.
|
|
12033
|
+
newOps.push(createVariableOp(view.job.allocateXrefId(), scope.contextVariables.get(name), variable));
|
|
11731
12034
|
}
|
|
11732
12035
|
// Add variables for all local references declared for elements in this scope.
|
|
11733
12036
|
for (const ref of scope.references) {
|
|
@@ -11740,15 +12043,46 @@ function generateVariablesInScopeForView(view, scope) {
|
|
|
11740
12043
|
return newOps;
|
|
11741
12044
|
}
|
|
11742
12045
|
|
|
12046
|
+
/**
|
|
12047
|
+
* Looks for the HasConst trait, indicating that an op or expression has some data which
|
|
12048
|
+
* should be collected into the constant array. Capable of collecting either a single literal value,
|
|
12049
|
+
* or an array literal.
|
|
12050
|
+
*/
|
|
12051
|
+
function phaseConstTraitCollection(job) {
|
|
12052
|
+
const collectGlobalConsts = (e) => {
|
|
12053
|
+
if (e instanceof ExpressionBase && hasConstTrait(e)) {
|
|
12054
|
+
// TODO: Figure out how to make this type narrowing work.
|
|
12055
|
+
const ea = e;
|
|
12056
|
+
if (ea.constValue !== null) {
|
|
12057
|
+
ea.constIndex = job.addConst(ea.constValue);
|
|
12058
|
+
}
|
|
12059
|
+
}
|
|
12060
|
+
return e;
|
|
12061
|
+
};
|
|
12062
|
+
for (const unit of job.units) {
|
|
12063
|
+
for (const op of unit.ops()) {
|
|
12064
|
+
if (hasConstTrait(op) && op.constValue !== null) {
|
|
12065
|
+
op.constIndex = job.addConst(op.makeExpression(op.constValue));
|
|
12066
|
+
}
|
|
12067
|
+
transformExpressionsInOp(op, collectGlobalConsts, VisitorContextFlag.None);
|
|
12068
|
+
}
|
|
12069
|
+
}
|
|
12070
|
+
}
|
|
12071
|
+
|
|
11743
12072
|
const STYLE_DOT = 'style.';
|
|
11744
12073
|
const CLASS_DOT = 'class.';
|
|
11745
12074
|
const STYLE_BANG = 'style!';
|
|
11746
12075
|
const CLASS_BANG = 'class!';
|
|
12076
|
+
const BANG_IMPORTANT = '!important';
|
|
11747
12077
|
function phaseHostStylePropertyParsing(job) {
|
|
11748
12078
|
for (const op of job.root.update) {
|
|
11749
12079
|
if (op.kind !== OpKind.Binding) {
|
|
11750
12080
|
continue;
|
|
11751
12081
|
}
|
|
12082
|
+
if (op.name.endsWith(BANG_IMPORTANT)) {
|
|
12083
|
+
// Delete any `!important` suffixes from the binding name.
|
|
12084
|
+
op.name = op.name.substring(0, op.name.length - BANG_IMPORTANT.length);
|
|
12085
|
+
}
|
|
11752
12086
|
if (op.name.startsWith(STYLE_DOT)) {
|
|
11753
12087
|
op.bindingKind = BindingKind.StyleProperty;
|
|
11754
12088
|
op.name = op.name.substring(STYLE_DOT.length);
|
|
@@ -11802,6 +12136,31 @@ function parseProperty$1(name) {
|
|
|
11802
12136
|
return { property, suffix };
|
|
11803
12137
|
}
|
|
11804
12138
|
|
|
12139
|
+
/**
|
|
12140
|
+
* Lifts i18n properties into the consts array.
|
|
12141
|
+
*/
|
|
12142
|
+
function phaseI18nConstCollection(job) {
|
|
12143
|
+
// Serialize the extracted messages into the const array.
|
|
12144
|
+
// TODO: Use `Map` instead of object.
|
|
12145
|
+
const messageConstIndices = {};
|
|
12146
|
+
for (const unit of job.units) {
|
|
12147
|
+
for (const op of unit.create) {
|
|
12148
|
+
if (op.kind === OpKind.ExtractedMessage) {
|
|
12149
|
+
messageConstIndices[op.owner] = job.addConst(op.expression, op.statements);
|
|
12150
|
+
OpList.remove(op);
|
|
12151
|
+
}
|
|
12152
|
+
}
|
|
12153
|
+
}
|
|
12154
|
+
// Assign const index to i18n ops that messages were extracted from.
|
|
12155
|
+
for (const unit of job.units) {
|
|
12156
|
+
for (const op of unit.create) {
|
|
12157
|
+
if (op.kind === OpKind.I18nStart || op.kind === OpKind.I18n) {
|
|
12158
|
+
op.messageIndex = messageConstIndices[op.root];
|
|
12159
|
+
}
|
|
12160
|
+
}
|
|
12161
|
+
}
|
|
12162
|
+
}
|
|
12163
|
+
|
|
11805
12164
|
function mapEntry(key, value) {
|
|
11806
12165
|
return { key, value, quoted: false };
|
|
11807
12166
|
}
|
|
@@ -16691,7 +17050,7 @@ class _Tokenizer {
|
|
|
16691
17050
|
new PlainCharacterCursor(_file, range);
|
|
16692
17051
|
this._preserveLineEndings = options.preserveLineEndings || false;
|
|
16693
17052
|
this._i18nNormalizeLineEndingsInICUs = options.i18nNormalizeLineEndingsInICUs || false;
|
|
16694
|
-
this._tokenizeBlocks = options.tokenizeBlocks
|
|
17053
|
+
this._tokenizeBlocks = options.tokenizeBlocks ?? true;
|
|
16695
17054
|
try {
|
|
16696
17055
|
this._cursor.init();
|
|
16697
17056
|
}
|
|
@@ -16749,7 +17108,7 @@ class _Tokenizer {
|
|
|
16749
17108
|
this.handleError(e);
|
|
16750
17109
|
}
|
|
16751
17110
|
}
|
|
16752
|
-
this._beginToken(
|
|
17111
|
+
this._beginToken(29 /* TokenType.EOF */);
|
|
16753
17112
|
this._endToken([]);
|
|
16754
17113
|
}
|
|
16755
17114
|
_getBlockName() {
|
|
@@ -16770,7 +17129,7 @@ class _Tokenizer {
|
|
|
16770
17129
|
}
|
|
16771
17130
|
_consumeBlockStart(start) {
|
|
16772
17131
|
this._beginToken(24 /* TokenType.BLOCK_OPEN_START */, start);
|
|
16773
|
-
this._endToken([this._getBlockName()]);
|
|
17132
|
+
const startToken = this._endToken([this._getBlockName()]);
|
|
16774
17133
|
if (this._cursor.peek() === $LPAREN) {
|
|
16775
17134
|
// Advance past the opening paren.
|
|
16776
17135
|
this._cursor.advance();
|
|
@@ -16778,14 +17137,22 @@ class _Tokenizer {
|
|
|
16778
17137
|
this._consumeBlockParameters();
|
|
16779
17138
|
// Allow spaces before the closing paren.
|
|
16780
17139
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16781
|
-
|
|
16782
|
-
|
|
16783
|
-
|
|
16784
|
-
|
|
17140
|
+
if (this._attemptCharCode($RPAREN)) {
|
|
17141
|
+
// Allow spaces after the paren.
|
|
17142
|
+
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
17143
|
+
}
|
|
17144
|
+
else {
|
|
17145
|
+
startToken.type = 28 /* TokenType.INCOMPLETE_BLOCK_OPEN */;
|
|
17146
|
+
return;
|
|
17147
|
+
}
|
|
17148
|
+
}
|
|
17149
|
+
if (this._attemptCharCode($LBRACE)) {
|
|
17150
|
+
this._beginToken(25 /* TokenType.BLOCK_OPEN_END */);
|
|
17151
|
+
this._endToken([]);
|
|
17152
|
+
}
|
|
17153
|
+
else {
|
|
17154
|
+
startToken.type = 28 /* TokenType.INCOMPLETE_BLOCK_OPEN */;
|
|
16785
17155
|
}
|
|
16786
|
-
this._beginToken(25 /* TokenType.BLOCK_OPEN_END */);
|
|
16787
|
-
this._requireCharCode($LBRACE);
|
|
16788
|
-
this._endToken([]);
|
|
16789
17156
|
}
|
|
16790
17157
|
_consumeBlockEnd(start) {
|
|
16791
17158
|
this._beginToken(26 /* TokenType.BLOCK_CLOSE */, start);
|
|
@@ -17758,7 +18125,7 @@ class _TreeBuilder {
|
|
|
17758
18125
|
this._advance();
|
|
17759
18126
|
}
|
|
17760
18127
|
build() {
|
|
17761
|
-
while (this._peek.type !==
|
|
18128
|
+
while (this._peek.type !== 29 /* TokenType.EOF */) {
|
|
17762
18129
|
if (this._peek.type === 0 /* TokenType.TAG_OPEN_START */ ||
|
|
17763
18130
|
this._peek.type === 4 /* TokenType.INCOMPLETE_TAG_OPEN */) {
|
|
17764
18131
|
this._consumeStartTag(this._advance());
|
|
@@ -17790,6 +18157,10 @@ class _TreeBuilder {
|
|
|
17790
18157
|
this._closeVoidElement();
|
|
17791
18158
|
this._consumeBlockClose(this._advance());
|
|
17792
18159
|
}
|
|
18160
|
+
else if (this._peek.type === 28 /* TokenType.INCOMPLETE_BLOCK_OPEN */) {
|
|
18161
|
+
this._closeVoidElement();
|
|
18162
|
+
this._consumeIncompleteBlock(this._advance());
|
|
18163
|
+
}
|
|
17793
18164
|
else {
|
|
17794
18165
|
// Skip all other tokens...
|
|
17795
18166
|
this._advance();
|
|
@@ -17863,7 +18234,7 @@ class _TreeBuilder {
|
|
|
17863
18234
|
if (!exp)
|
|
17864
18235
|
return null;
|
|
17865
18236
|
const end = this._advance();
|
|
17866
|
-
exp.push({ type:
|
|
18237
|
+
exp.push({ type: 29 /* TokenType.EOF */, parts: [], sourceSpan: end.sourceSpan });
|
|
17867
18238
|
// parse everything in between { and }
|
|
17868
18239
|
const expansionCaseParser = new _TreeBuilder(exp, this.getTagDefinition);
|
|
17869
18240
|
expansionCaseParser.build();
|
|
@@ -17903,7 +18274,7 @@ class _TreeBuilder {
|
|
|
17903
18274
|
return null;
|
|
17904
18275
|
}
|
|
17905
18276
|
}
|
|
17906
|
-
if (this._peek.type ===
|
|
18277
|
+
if (this._peek.type === 29 /* TokenType.EOF */) {
|
|
17907
18278
|
this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
|
|
17908
18279
|
return null;
|
|
17909
18280
|
}
|
|
@@ -18105,16 +18476,30 @@ class _TreeBuilder {
|
|
|
18105
18476
|
const startSpan = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
|
|
18106
18477
|
const block = new Block(token.parts[0], parameters, [], span, startSpan);
|
|
18107
18478
|
this._pushContainer(block, false);
|
|
18108
|
-
return block;
|
|
18109
18479
|
}
|
|
18110
18480
|
_consumeBlockClose(token) {
|
|
18111
|
-
const previousContainer = this._getContainer();
|
|
18112
18481
|
if (!this._popContainer(null, Block, token.sourceSpan)) {
|
|
18113
|
-
|
|
18114
|
-
`
|
|
18115
|
-
`
|
|
18116
|
-
|
|
18482
|
+
this.errors.push(TreeError.create(null, token.sourceSpan, `Unexpected closing block. The block may have been closed earlier. ` +
|
|
18483
|
+
`If you meant to write the } character, you should use the "}" ` +
|
|
18484
|
+
`HTML entity instead.`));
|
|
18485
|
+
}
|
|
18486
|
+
}
|
|
18487
|
+
_consumeIncompleteBlock(token) {
|
|
18488
|
+
const parameters = [];
|
|
18489
|
+
while (this._peek.type === 27 /* TokenType.BLOCK_PARAMETER */) {
|
|
18490
|
+
const paramToken = this._advance();
|
|
18491
|
+
parameters.push(new BlockParameter(paramToken.parts[0], paramToken.sourceSpan));
|
|
18117
18492
|
}
|
|
18493
|
+
const end = this._peek.sourceSpan.fullStart;
|
|
18494
|
+
const span = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
|
|
18495
|
+
// Create a separate `startSpan` because `span` will be modified when there is an `end` span.
|
|
18496
|
+
const startSpan = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
|
|
18497
|
+
const block = new Block(token.parts[0], parameters, [], span, startSpan);
|
|
18498
|
+
this._pushContainer(block, false);
|
|
18499
|
+
// Incomplete blocks don't have children so we close them immediately and report an error.
|
|
18500
|
+
this._popContainer(null, Block, null);
|
|
18501
|
+
this.errors.push(TreeError.create(token.parts[0], span, `Incomplete block "${token.parts[0]}". If you meant to write the @ character, ` +
|
|
18502
|
+
`you should use the "@" HTML entity instead.`));
|
|
18118
18503
|
}
|
|
18119
18504
|
_getContainer() {
|
|
18120
18505
|
return this._containerStack.length > 0 ? this._containerStack[this._containerStack.length - 1] :
|
|
@@ -18668,17 +19053,20 @@ function phaseI18nMessageExtraction(job) {
|
|
|
18668
19053
|
const fileBasedI18nSuffix = job.relativeContextFilePath.replace(/[^A-Za-z0-9]/g, '_').toUpperCase() + '_';
|
|
18669
19054
|
for (const unit of job.units) {
|
|
18670
19055
|
for (const op of unit.create) {
|
|
18671
|
-
if (op.kind === OpKind.I18nStart
|
|
18672
|
-
//
|
|
18673
|
-
|
|
18674
|
-
|
|
18675
|
-
|
|
18676
|
-
|
|
18677
|
-
|
|
18678
|
-
|
|
18679
|
-
|
|
18680
|
-
|
|
18681
|
-
|
|
19056
|
+
if ((op.kind === OpKind.I18nStart || op.kind === OpKind.I18n)) {
|
|
19057
|
+
// Only extract messages from root i18n ops, not sub-template ones.
|
|
19058
|
+
if (op.xref === op.root) {
|
|
19059
|
+
// Sort the params map to match the ordering in TemplateDefinitionBuilder.
|
|
19060
|
+
const params = new Map([...op.params.entries()].sort());
|
|
19061
|
+
const mainVar = variable(job.pool.uniqueName(TRANSLATION_VAR_PREFIX));
|
|
19062
|
+
// Closure Compiler requires const names to start with `MSG_` but disallows any other
|
|
19063
|
+
// const to start with `MSG_`. We define a variable starting with `MSG_` just for the
|
|
19064
|
+
// `goog.getMsg` call
|
|
19065
|
+
const closureVar = i18nGenerateClosureVar(job.pool, op.message.id, fileBasedI18nSuffix, job.i18nUseExternalIds);
|
|
19066
|
+
// TODO: figure out transformFn.
|
|
19067
|
+
const statements = getTranslationDeclStmts$1(op.message, mainVar, closureVar, params, undefined /*transformFn*/);
|
|
19068
|
+
unit.create.push(createExtractedMessageOp(op.xref, mainVar, statements));
|
|
19069
|
+
}
|
|
18682
19070
|
}
|
|
18683
19071
|
}
|
|
18684
19072
|
}
|
|
@@ -18709,10 +19097,11 @@ function phaseI18nMessageExtraction(job) {
|
|
|
18709
19097
|
* post-processing).
|
|
18710
19098
|
* @returns An array of statements that defined a given translation.
|
|
18711
19099
|
*/
|
|
18712
|
-
function getTranslationDeclStmts$1(message, variable, closureVar, params
|
|
19100
|
+
function getTranslationDeclStmts$1(message, variable, closureVar, params, transformFn) {
|
|
19101
|
+
const paramsObject = Object.fromEntries(params);
|
|
18713
19102
|
const statements = [
|
|
18714
19103
|
declareI18nVariable(variable),
|
|
18715
|
-
ifStmt(createClosureModeGuard$1(), createGoogleGetMsgStatements(variable, message, closureVar,
|
|
19104
|
+
ifStmt(createClosureModeGuard$1(), createGoogleGetMsgStatements(variable, message, closureVar, paramsObject), createLocalizeStatements(variable, message, formatI18nPlaceholderNamesInMap(paramsObject, /* useCamelCase */ false))),
|
|
18716
19105
|
];
|
|
18717
19106
|
if (transformFn) {
|
|
18718
19107
|
statements.push(new ExpressionStatement(variable.set(transformFn(variable))));
|
|
@@ -18755,22 +19144,48 @@ function i18nGenerateClosureVar(pool, messageId, fileBasedI18nSuffix, useExterna
|
|
|
18755
19144
|
*/
|
|
18756
19145
|
function phaseI18nTextExtraction(job) {
|
|
18757
19146
|
for (const unit of job.units) {
|
|
18758
|
-
|
|
19147
|
+
// Remove all text nodes within i18n blocks, their content is already captured in the i18n
|
|
19148
|
+
// message.
|
|
19149
|
+
let currentI18nId = null;
|
|
19150
|
+
const textNodes = new Map();
|
|
18759
19151
|
for (const op of unit.create) {
|
|
18760
19152
|
switch (op.kind) {
|
|
18761
19153
|
case OpKind.I18nStart:
|
|
18762
|
-
|
|
19154
|
+
currentI18nId = op.xref;
|
|
18763
19155
|
break;
|
|
18764
19156
|
case OpKind.I18nEnd:
|
|
18765
|
-
|
|
19157
|
+
currentI18nId = null;
|
|
18766
19158
|
break;
|
|
18767
19159
|
case OpKind.Text:
|
|
18768
|
-
if (
|
|
19160
|
+
if (currentI18nId !== null) {
|
|
19161
|
+
textNodes.set(op.xref, currentI18nId);
|
|
18769
19162
|
OpList.remove(op);
|
|
18770
19163
|
}
|
|
18771
19164
|
break;
|
|
18772
19165
|
}
|
|
18773
19166
|
}
|
|
19167
|
+
// Update any interpolations to the removed text, and instead represent them as a series of i18n
|
|
19168
|
+
// expressions that we then apply.
|
|
19169
|
+
for (const op of unit.update) {
|
|
19170
|
+
switch (op.kind) {
|
|
19171
|
+
case OpKind.InterpolateText:
|
|
19172
|
+
if (!textNodes.has(op.target)) {
|
|
19173
|
+
continue;
|
|
19174
|
+
}
|
|
19175
|
+
const i18nBlockId = textNodes.get(op.target);
|
|
19176
|
+
const ops = [];
|
|
19177
|
+
for (let i = 0; i < op.interpolation.expressions.length; i++) {
|
|
19178
|
+
const expr = op.interpolation.expressions[i];
|
|
19179
|
+
const placeholder = op.i18nPlaceholders[i];
|
|
19180
|
+
ops.push(createI18nExpressionOp(i18nBlockId, expr, placeholder, expr.sourceSpan ?? op.sourceSpan));
|
|
19181
|
+
}
|
|
19182
|
+
if (ops.length > 0) {
|
|
19183
|
+
// ops.push(ir.createI18nApplyOp(i18nBlockId, op.i18nPlaceholders, op.sourceSpan));
|
|
19184
|
+
}
|
|
19185
|
+
OpList.replaceWithMany(op, ops);
|
|
19186
|
+
break;
|
|
19187
|
+
}
|
|
19188
|
+
}
|
|
18774
19189
|
}
|
|
18775
19190
|
}
|
|
18776
19191
|
|
|
@@ -18934,7 +19349,7 @@ function addNamesToView(unit, baseName, state, compatibility) {
|
|
|
18934
19349
|
if (op.handlerFnName !== null) {
|
|
18935
19350
|
break;
|
|
18936
19351
|
}
|
|
18937
|
-
if (!op.hostListener && op.
|
|
19352
|
+
if (!op.hostListener && op.targetSlot === null) {
|
|
18938
19353
|
throw new Error(`Expected a slot to be assigned`);
|
|
18939
19354
|
}
|
|
18940
19355
|
let animation = '';
|
|
@@ -18946,7 +19361,7 @@ function addNamesToView(unit, baseName, state, compatibility) {
|
|
|
18946
19361
|
op.handlerFnName = `${baseName}_${animation}${op.name}_HostBindingHandler`;
|
|
18947
19362
|
}
|
|
18948
19363
|
else {
|
|
18949
|
-
op.handlerFnName = `${unit.fnName}_${op.tag.replace('-', '_')}_${animation}${op.name}_${op.
|
|
19364
|
+
op.handlerFnName = `${unit.fnName}_${op.tag.replace('-', '_')}_${animation}${op.name}_${op.targetSlot}_listener`;
|
|
18950
19365
|
}
|
|
18951
19366
|
op.handlerFnName = sanitizeIdentifier(op.handlerFnName);
|
|
18952
19367
|
break;
|
|
@@ -19095,6 +19510,11 @@ function phaseNgContainer(job) {
|
|
|
19095
19510
|
for (const unit of job.units) {
|
|
19096
19511
|
const updatedElementXrefs = new Set();
|
|
19097
19512
|
for (const op of unit.create) {
|
|
19513
|
+
if (op.kind === OpKind.Element && op.tag === CONTAINER_TAG) {
|
|
19514
|
+
// Transmute the `Element` instruction to `Container`.
|
|
19515
|
+
op.kind = OpKind.Container;
|
|
19516
|
+
updatedElementXrefs.add(op.xref);
|
|
19517
|
+
}
|
|
19098
19518
|
if (op.kind === OpKind.ElementStart && op.tag === CONTAINER_TAG) {
|
|
19099
19519
|
// Transmute the `ElementStart` instruction to `ContainerStart`.
|
|
19100
19520
|
op.kind = OpKind.ContainerStart;
|
|
@@ -19108,30 +19528,6 @@ function phaseNgContainer(job) {
|
|
|
19108
19528
|
}
|
|
19109
19529
|
}
|
|
19110
19530
|
|
|
19111
|
-
function phaseNoListenersOnTemplates(job) {
|
|
19112
|
-
for (const unit of job.units) {
|
|
19113
|
-
let inTemplate = false;
|
|
19114
|
-
for (const op of unit.create) {
|
|
19115
|
-
switch (op.kind) {
|
|
19116
|
-
case OpKind.Template:
|
|
19117
|
-
inTemplate = true;
|
|
19118
|
-
break;
|
|
19119
|
-
case OpKind.ElementStart:
|
|
19120
|
-
case OpKind.Element:
|
|
19121
|
-
case OpKind.ContainerStart:
|
|
19122
|
-
case OpKind.Container:
|
|
19123
|
-
inTemplate = false;
|
|
19124
|
-
break;
|
|
19125
|
-
case OpKind.Listener:
|
|
19126
|
-
if (inTemplate) {
|
|
19127
|
-
OpList.remove(op);
|
|
19128
|
-
}
|
|
19129
|
-
break;
|
|
19130
|
-
}
|
|
19131
|
-
}
|
|
19132
|
-
}
|
|
19133
|
-
}
|
|
19134
|
-
|
|
19135
19531
|
/**
|
|
19136
19532
|
* Looks up an element in the given map by xref ID.
|
|
19137
19533
|
*/
|
|
@@ -19189,6 +19585,95 @@ function phaseNullishCoalescing(job) {
|
|
|
19189
19585
|
}
|
|
19190
19586
|
}
|
|
19191
19587
|
|
|
19588
|
+
function kindTest(kind) {
|
|
19589
|
+
return (op) => op.kind === kind;
|
|
19590
|
+
}
|
|
19591
|
+
/**
|
|
19592
|
+
* Defines the groups based on `OpKind` that ops will be divided into, for the various create
|
|
19593
|
+
* binding kinds. Ops will be collected into groups, then optionally transformed, before recombining
|
|
19594
|
+
* the groups in the order defined here.
|
|
19595
|
+
*/
|
|
19596
|
+
const CREATE_ORDERING = [
|
|
19597
|
+
{ test: op => op.kind === OpKind.Listener && op.hostListener && op.isAnimationListener },
|
|
19598
|
+
{ test: op => op.kind === OpKind.Listener && !(op.hostListener && op.isAnimationListener) },
|
|
19599
|
+
];
|
|
19600
|
+
/**
|
|
19601
|
+
* As above, but for update ops.
|
|
19602
|
+
*/
|
|
19603
|
+
const UPDATE_ORDERING = [
|
|
19604
|
+
{ test: op => op.kind === OpKind.HostProperty && op.expression instanceof Interpolation },
|
|
19605
|
+
{ test: op => op.kind === OpKind.HostProperty && !(op.expression instanceof Interpolation) },
|
|
19606
|
+
{ test: kindTest(OpKind.StyleMap), transform: keepLast },
|
|
19607
|
+
{ test: kindTest(OpKind.ClassMap), transform: keepLast },
|
|
19608
|
+
{ test: kindTest(OpKind.StyleProp) },
|
|
19609
|
+
{ test: kindTest(OpKind.ClassProp) },
|
|
19610
|
+
{ test: op => op.kind === OpKind.Property && op.expression instanceof Interpolation },
|
|
19611
|
+
{ test: op => op.kind === OpKind.Property && !(op.expression instanceof Interpolation) },
|
|
19612
|
+
{ test: kindTest(OpKind.Attribute) },
|
|
19613
|
+
];
|
|
19614
|
+
/**
|
|
19615
|
+
* The set of all op kinds we handle in the reordering phase.
|
|
19616
|
+
*/
|
|
19617
|
+
const handledOpKinds = new Set([
|
|
19618
|
+
OpKind.Listener, OpKind.StyleMap, OpKind.ClassMap, OpKind.StyleProp,
|
|
19619
|
+
OpKind.ClassProp, OpKind.Property, OpKind.HostProperty, OpKind.Attribute
|
|
19620
|
+
]);
|
|
19621
|
+
function phaseOrdering(job) {
|
|
19622
|
+
for (const unit of job.units) {
|
|
19623
|
+
// First, we pull out ops that need to be ordered. Then, when we encounter an op that shouldn't
|
|
19624
|
+
// be reordered, put the ones we've pulled so far back in the correct order. Finally, if we
|
|
19625
|
+
// still have ops pulled at the end, put them back in the correct order.
|
|
19626
|
+
// Create mode:
|
|
19627
|
+
let opsToOrder = [];
|
|
19628
|
+
for (const op of unit.create) {
|
|
19629
|
+
if (handledOpKinds.has(op.kind)) {
|
|
19630
|
+
opsToOrder.push(op);
|
|
19631
|
+
OpList.remove(op);
|
|
19632
|
+
}
|
|
19633
|
+
else {
|
|
19634
|
+
OpList.insertBefore(reorder(opsToOrder, CREATE_ORDERING), op);
|
|
19635
|
+
opsToOrder = [];
|
|
19636
|
+
}
|
|
19637
|
+
}
|
|
19638
|
+
unit.create.push(reorder(opsToOrder, CREATE_ORDERING));
|
|
19639
|
+
// Update mode:
|
|
19640
|
+
opsToOrder = [];
|
|
19641
|
+
for (const op of unit.update) {
|
|
19642
|
+
if (handledOpKinds.has(op.kind)) {
|
|
19643
|
+
opsToOrder.push(op);
|
|
19644
|
+
OpList.remove(op);
|
|
19645
|
+
}
|
|
19646
|
+
else {
|
|
19647
|
+
OpList.insertBefore(reorder(opsToOrder, UPDATE_ORDERING), op);
|
|
19648
|
+
opsToOrder = [];
|
|
19649
|
+
}
|
|
19650
|
+
}
|
|
19651
|
+
unit.update.push(reorder(opsToOrder, UPDATE_ORDERING));
|
|
19652
|
+
}
|
|
19653
|
+
}
|
|
19654
|
+
/**
|
|
19655
|
+
* Reorders the given list of ops according to the ordering defined by `ORDERING`.
|
|
19656
|
+
*/
|
|
19657
|
+
function reorder(ops, ordering) {
|
|
19658
|
+
// Break the ops list into groups based on OpKind.
|
|
19659
|
+
const groups = Array.from(ordering, () => new Array());
|
|
19660
|
+
for (const op of ops) {
|
|
19661
|
+
const groupIndex = ordering.findIndex(o => o.test(op));
|
|
19662
|
+
groups[groupIndex].push(op);
|
|
19663
|
+
}
|
|
19664
|
+
// Reassemble the groups into a single list, in the correct order.
|
|
19665
|
+
return groups.flatMap((group, i) => {
|
|
19666
|
+
const transform = ordering[i].transform;
|
|
19667
|
+
return transform ? transform(group) : group;
|
|
19668
|
+
});
|
|
19669
|
+
}
|
|
19670
|
+
/**
|
|
19671
|
+
* Keeps only the last op in a list of ops.
|
|
19672
|
+
*/
|
|
19673
|
+
function keepLast(ops) {
|
|
19674
|
+
return ops.slice(ops.length - 1);
|
|
19675
|
+
}
|
|
19676
|
+
|
|
19192
19677
|
/**
|
|
19193
19678
|
* Parses extracted style and class attributes into separate ExtractedAttributeOps per style or
|
|
19194
19679
|
* class property.
|
|
@@ -19217,6 +19702,36 @@ function phaseParseExtractedStyles(cpl) {
|
|
|
19217
19702
|
}
|
|
19218
19703
|
}
|
|
19219
19704
|
|
|
19705
|
+
/**
|
|
19706
|
+
* Attributes of `ng-content` named 'select' are specifically removed, because they control which
|
|
19707
|
+
* content matches as a property of the `projection`, and are not a plain attribute.
|
|
19708
|
+
*/
|
|
19709
|
+
function phaseRemoveContentSelectors(job) {
|
|
19710
|
+
for (const unit of job.units) {
|
|
19711
|
+
const elements = getElementsByXrefId(unit);
|
|
19712
|
+
for (const op of unit.update) {
|
|
19713
|
+
switch (op.kind) {
|
|
19714
|
+
case OpKind.Binding:
|
|
19715
|
+
const target = lookupElement(elements, op.target);
|
|
19716
|
+
if (op.name.toLowerCase() === 'select' && target.kind === OpKind.Projection) {
|
|
19717
|
+
OpList.remove(op);
|
|
19718
|
+
}
|
|
19719
|
+
continue;
|
|
19720
|
+
}
|
|
19721
|
+
}
|
|
19722
|
+
}
|
|
19723
|
+
}
|
|
19724
|
+
/**
|
|
19725
|
+
* Looks up an element in the given map by xref ID.
|
|
19726
|
+
*/
|
|
19727
|
+
function lookupElement(elements, xref) {
|
|
19728
|
+
const el = elements.get(xref);
|
|
19729
|
+
if (el === undefined) {
|
|
19730
|
+
throw new Error('All attributes should have an element-like target.');
|
|
19731
|
+
}
|
|
19732
|
+
return el;
|
|
19733
|
+
}
|
|
19734
|
+
|
|
19220
19735
|
function phasePipeCreation(job) {
|
|
19221
19736
|
for (const unit of job.units) {
|
|
19222
19737
|
processPipeBindingsInView(unit);
|
|
@@ -19283,93 +19798,84 @@ function phasePipeVariadic(job) {
|
|
|
19283
19798
|
}
|
|
19284
19799
|
}
|
|
19285
19800
|
|
|
19286
|
-
function kindTest(kind) {
|
|
19287
|
-
return (op) => op.kind === kind;
|
|
19288
|
-
}
|
|
19289
19801
|
/**
|
|
19290
|
-
*
|
|
19291
|
-
*
|
|
19292
|
-
* the groups in the order defined here.
|
|
19802
|
+
* Propagate i18n blocks down through child templates that act as placeholders in the root i18n
|
|
19803
|
+
* message.
|
|
19293
19804
|
*/
|
|
19294
|
-
|
|
19295
|
-
|
|
19296
|
-
|
|
19297
|
-
];
|
|
19805
|
+
function phasePropagateI18nBlocks(job) {
|
|
19806
|
+
propagateI18nBlocksToTemplates(job.root, 0);
|
|
19807
|
+
}
|
|
19298
19808
|
/**
|
|
19299
|
-
*
|
|
19809
|
+
* Propagates i18n ops in the given view through to any child views recursively.
|
|
19300
19810
|
*/
|
|
19301
|
-
|
|
19302
|
-
|
|
19303
|
-
|
|
19304
|
-
|
|
19305
|
-
|
|
19306
|
-
|
|
19307
|
-
|
|
19308
|
-
|
|
19309
|
-
|
|
19310
|
-
|
|
19311
|
-
|
|
19811
|
+
function propagateI18nBlocksToTemplates(unit, subTemplateIndex) {
|
|
19812
|
+
let i18nBlock = null;
|
|
19813
|
+
for (const op of unit.create) {
|
|
19814
|
+
switch (op.kind) {
|
|
19815
|
+
case OpKind.I18nStart:
|
|
19816
|
+
op.subTemplateIndex = subTemplateIndex === 0 ? null : subTemplateIndex;
|
|
19817
|
+
i18nBlock = op;
|
|
19818
|
+
break;
|
|
19819
|
+
case OpKind.I18nEnd:
|
|
19820
|
+
i18nBlock = null;
|
|
19821
|
+
break;
|
|
19822
|
+
case OpKind.Template:
|
|
19823
|
+
const templateView = unit.job.views.get(op.xref);
|
|
19824
|
+
// We found an <ng-template> inside an i18n block; increment the sub-template counter and
|
|
19825
|
+
// wrap the template's view in a child i18n block.
|
|
19826
|
+
if (op.i18nPlaceholder !== undefined) {
|
|
19827
|
+
if (i18nBlock === null) {
|
|
19828
|
+
throw Error('Expected template with i18n placeholder to be in an i18n block.');
|
|
19829
|
+
}
|
|
19830
|
+
subTemplateIndex++;
|
|
19831
|
+
wrapTemplateWithI18n(templateView, i18nBlock);
|
|
19832
|
+
}
|
|
19833
|
+
// Continue traversing inside the template's view.
|
|
19834
|
+
propagateI18nBlocksToTemplates(templateView, subTemplateIndex);
|
|
19835
|
+
}
|
|
19836
|
+
}
|
|
19837
|
+
}
|
|
19312
19838
|
/**
|
|
19313
|
-
*
|
|
19839
|
+
* Wraps a template view with i18n start and end ops.
|
|
19314
19840
|
*/
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
|
|
19318
|
-
|
|
19319
|
-
|
|
19841
|
+
function wrapTemplateWithI18n(unit, parentI18n) {
|
|
19842
|
+
// Only add i18n ops if they have not already been propagated to this template.
|
|
19843
|
+
if (unit.create.head.next?.kind !== OpKind.I18nStart) {
|
|
19844
|
+
const id = unit.job.allocateXrefId();
|
|
19845
|
+
OpList.insertAfter(createI18nStartOp(id, parentI18n.message, parentI18n.root), unit.create.head);
|
|
19846
|
+
OpList.insertBefore(createI18nEndOp(id), unit.create.tail);
|
|
19847
|
+
}
|
|
19848
|
+
}
|
|
19849
|
+
|
|
19850
|
+
function phasePropagateI18nPlaceholders(job) {
|
|
19851
|
+
// Get all of the i18n ops.
|
|
19852
|
+
const i18nOps = new Map();
|
|
19320
19853
|
for (const unit of job.units) {
|
|
19321
|
-
// First, we pull out ops that need to be ordered. Then, when we encounter an op that shouldn't
|
|
19322
|
-
// be reordered, put the ones we've pulled so far back in the correct order. Finally, if we
|
|
19323
|
-
// still have ops pulled at the end, put them back in the correct order.
|
|
19324
|
-
// Create mode:
|
|
19325
|
-
let opsToOrder = [];
|
|
19326
19854
|
for (const op of unit.create) {
|
|
19327
|
-
if (
|
|
19328
|
-
|
|
19329
|
-
OpList.remove(op);
|
|
19330
|
-
}
|
|
19331
|
-
else {
|
|
19332
|
-
OpList.insertBefore(reorder(opsToOrder, CREATE_ORDERING), op);
|
|
19333
|
-
opsToOrder = [];
|
|
19855
|
+
if (op.kind === OpKind.I18nStart) {
|
|
19856
|
+
i18nOps.set(op.xref, op);
|
|
19334
19857
|
}
|
|
19335
19858
|
}
|
|
19336
|
-
|
|
19337
|
-
|
|
19338
|
-
|
|
19339
|
-
|
|
19340
|
-
|
|
19341
|
-
|
|
19342
|
-
|
|
19343
|
-
}
|
|
19344
|
-
else {
|
|
19345
|
-
OpList.insertBefore(reorder(opsToOrder, UPDATE_ORDERING), op);
|
|
19346
|
-
opsToOrder = [];
|
|
19859
|
+
}
|
|
19860
|
+
// Propagate i18n params from sub-templates up to the root i18n op.
|
|
19861
|
+
for (const op of i18nOps.values()) {
|
|
19862
|
+
if (op.xref !== op.root) {
|
|
19863
|
+
const rootOp = i18nOps.get(op.root);
|
|
19864
|
+
for (const [placeholder, value] of op.params) {
|
|
19865
|
+
rootOp.params.set(placeholder, value);
|
|
19347
19866
|
}
|
|
19348
19867
|
}
|
|
19349
|
-
unit.update.push(reorder(opsToOrder, UPDATE_ORDERING));
|
|
19350
19868
|
}
|
|
19351
|
-
|
|
19352
|
-
|
|
19353
|
-
|
|
19354
|
-
|
|
19355
|
-
|
|
19356
|
-
|
|
19357
|
-
|
|
19358
|
-
|
|
19359
|
-
|
|
19360
|
-
groups[groupIndex].push(op);
|
|
19869
|
+
// Validate the root i18n ops have all placeholders filled in.
|
|
19870
|
+
for (const op of i18nOps.values()) {
|
|
19871
|
+
if (op.xref === op.root) {
|
|
19872
|
+
for (const placeholder in op.message.placeholders) {
|
|
19873
|
+
if (!op.params.has(placeholder)) {
|
|
19874
|
+
throw Error(`Failed to resolve i18n placeholder: ${placeholder}`);
|
|
19875
|
+
}
|
|
19876
|
+
}
|
|
19877
|
+
}
|
|
19361
19878
|
}
|
|
19362
|
-
// Reassemble the groups into a single list, in the correct order.
|
|
19363
|
-
return groups.flatMap((group, i) => {
|
|
19364
|
-
const transform = ordering[i].transform;
|
|
19365
|
-
return transform ? transform(group) : group;
|
|
19366
|
-
});
|
|
19367
|
-
}
|
|
19368
|
-
/**
|
|
19369
|
-
* Keeps only the last op in a list of ops.
|
|
19370
|
-
*/
|
|
19371
|
-
function keepLast(ops) {
|
|
19372
|
-
return ops.slice(ops.length - 1);
|
|
19373
19879
|
}
|
|
19374
19880
|
|
|
19375
19881
|
function phasePureFunctionExtraction(job) {
|
|
@@ -19402,7 +19908,7 @@ class PureFunctionConstant extends GenericKeyFn {
|
|
|
19402
19908
|
toSharedConstantDeclaration(declName, keyExpr) {
|
|
19403
19909
|
const fnParams = [];
|
|
19404
19910
|
for (let idx = 0; idx < this.numArgs; idx++) {
|
|
19405
|
-
fnParams.push(new FnParam('
|
|
19911
|
+
fnParams.push(new FnParam('a' + idx));
|
|
19406
19912
|
}
|
|
19407
19913
|
// We will never visit `ir.PureFunctionParameterExpr`s that don't belong to us, because this
|
|
19408
19914
|
// transform runs inside another visitor which will visit nested pure functions before this one.
|
|
@@ -19410,9 +19916,9 @@ class PureFunctionConstant extends GenericKeyFn {
|
|
|
19410
19916
|
if (!(expr instanceof PureFunctionParameterExpr)) {
|
|
19411
19917
|
return expr;
|
|
19412
19918
|
}
|
|
19413
|
-
return variable('
|
|
19919
|
+
return variable('a' + expr.index);
|
|
19414
19920
|
}, VisitorContextFlag.None);
|
|
19415
|
-
return new
|
|
19921
|
+
return new DeclareVarStmt(declName, new ArrowFunctionExpr(fnParams, returnExpr), undefined, StmtModifier.Final);
|
|
19416
19922
|
}
|
|
19417
19923
|
}
|
|
19418
19924
|
|
|
@@ -19576,6 +20082,25 @@ function text(slot, initialValue, sourceSpan) {
|
|
|
19576
20082
|
}
|
|
19577
20083
|
return call(Identifiers.text, args, sourceSpan);
|
|
19578
20084
|
}
|
|
20085
|
+
function defer(selfSlot, primarySlot, dependencyResolverFn, loadingSlot, placeholderSlot, errorSlot, loadingConfigIndex, placeholderConfigIndex, sourceSpan) {
|
|
20086
|
+
const args = [
|
|
20087
|
+
literal(selfSlot),
|
|
20088
|
+
literal(primarySlot),
|
|
20089
|
+
literal(dependencyResolverFn),
|
|
20090
|
+
literal(loadingSlot),
|
|
20091
|
+
literal(placeholderSlot),
|
|
20092
|
+
literal(errorSlot),
|
|
20093
|
+
literal(loadingConfigIndex),
|
|
20094
|
+
literal(placeholderConfigIndex),
|
|
20095
|
+
];
|
|
20096
|
+
while (args[args.length - 1].value === null) {
|
|
20097
|
+
args.pop();
|
|
20098
|
+
}
|
|
20099
|
+
return call(Identifiers.defer, args, sourceSpan);
|
|
20100
|
+
}
|
|
20101
|
+
function deferOn(sourceSpan) {
|
|
20102
|
+
return call(Identifiers.deferOnIdle, [], sourceSpan);
|
|
20103
|
+
}
|
|
19579
20104
|
function projectionDef(def) {
|
|
19580
20105
|
return call(Identifiers.projectionDef, def ? [def] : [], null);
|
|
19581
20106
|
}
|
|
@@ -19589,11 +20114,19 @@ function projection(slot, projectionSlotIndex, attributes) {
|
|
|
19589
20114
|
}
|
|
19590
20115
|
return call(Identifiers.projection, args, null);
|
|
19591
20116
|
}
|
|
19592
|
-
function i18nStart(slot, constIndex) {
|
|
19593
|
-
|
|
20117
|
+
function i18nStart(slot, constIndex, subTemplateIndex) {
|
|
20118
|
+
const args = [literal(slot), literal(constIndex)];
|
|
20119
|
+
if (subTemplateIndex !== null) {
|
|
20120
|
+
args.push(literal(subTemplateIndex));
|
|
20121
|
+
}
|
|
20122
|
+
return call(Identifiers.i18nStart, args, null);
|
|
19594
20123
|
}
|
|
19595
|
-
function i18n(slot) {
|
|
19596
|
-
|
|
20124
|
+
function i18n(slot, constIndex, subTemplateIndex) {
|
|
20125
|
+
const args = [literal(slot), literal(constIndex)];
|
|
20126
|
+
if (subTemplateIndex) {
|
|
20127
|
+
args.push(literal(subTemplateIndex));
|
|
20128
|
+
}
|
|
20129
|
+
return call(Identifiers.i18n, args, null);
|
|
19597
20130
|
}
|
|
19598
20131
|
function i18nEnd() {
|
|
19599
20132
|
return call(Identifiers.i18nEnd, [], null);
|
|
@@ -19670,6 +20203,12 @@ function textInterpolate(strings, expressions, sourceSpan) {
|
|
|
19670
20203
|
}
|
|
19671
20204
|
return callVariadicInstruction(TEXT_INTERPOLATE_CONFIG, [], interpolationArgs, [], sourceSpan);
|
|
19672
20205
|
}
|
|
20206
|
+
function i18nExp(expr, sourceSpan) {
|
|
20207
|
+
return call(Identifiers.i18nExp, [expr], sourceSpan);
|
|
20208
|
+
}
|
|
20209
|
+
function i18nApply(slot, sourceSpan) {
|
|
20210
|
+
return call(Identifiers.i18nApply, [literal(slot)], sourceSpan);
|
|
20211
|
+
}
|
|
19673
20212
|
function propertyInterpolate(name, strings, expressions, sanitizer, sourceSpan) {
|
|
19674
20213
|
const interpolationArgs = collateInterpolationArgs(strings, expressions);
|
|
19675
20214
|
const extraArgs = [];
|
|
@@ -19739,8 +20278,12 @@ function call(instruction, args, sourceSpan) {
|
|
|
19739
20278
|
const expr = importExpr(instruction).callFn(args, sourceSpan);
|
|
19740
20279
|
return createStatementOp(new ExpressionStatement(expr, sourceSpan));
|
|
19741
20280
|
}
|
|
19742
|
-
function conditional(slot, condition) {
|
|
19743
|
-
|
|
20281
|
+
function conditional(slot, condition, contextValue, sourceSpan) {
|
|
20282
|
+
const args = [literal(slot), condition];
|
|
20283
|
+
if (contextValue !== null) {
|
|
20284
|
+
args.push(contextValue);
|
|
20285
|
+
}
|
|
20286
|
+
return call(Identifiers.conditional, args, sourceSpan);
|
|
19744
20287
|
}
|
|
19745
20288
|
/**
|
|
19746
20289
|
* `InterpolationConfig` for the `textInterpolate` instruction.
|
|
@@ -19966,20 +20509,20 @@ function reifyCreateOperations(unit, ops) {
|
|
|
19966
20509
|
OpList.replace(op, elementContainerEnd());
|
|
19967
20510
|
break;
|
|
19968
20511
|
case OpKind.I18nStart:
|
|
19969
|
-
OpList.replace(op, i18nStart(op.slot, op.messageIndex));
|
|
20512
|
+
OpList.replace(op, i18nStart(op.slot, op.messageIndex, op.subTemplateIndex));
|
|
19970
20513
|
break;
|
|
19971
20514
|
case OpKind.I18nEnd:
|
|
19972
20515
|
OpList.replace(op, i18nEnd());
|
|
19973
20516
|
break;
|
|
19974
20517
|
case OpKind.I18n:
|
|
19975
|
-
OpList.replace(op, i18n(op.slot));
|
|
20518
|
+
OpList.replace(op, i18n(op.slot, op.messageIndex, op.subTemplateIndex));
|
|
19976
20519
|
break;
|
|
19977
20520
|
case OpKind.Template:
|
|
19978
20521
|
if (!(unit instanceof ViewCompilationUnit)) {
|
|
19979
20522
|
throw new Error(`AssertionError: must be compiling a component`);
|
|
19980
20523
|
}
|
|
19981
20524
|
const childView = unit.job.views.get(op.xref);
|
|
19982
|
-
OpList.replace(op, template(op.slot, variable(childView.fnName), childView.decls, childView.vars, op.
|
|
20525
|
+
OpList.replace(op, template(op.slot, variable(childView.fnName), childView.decls, childView.vars, op.block ? null : op.tag, op.attributes, op.sourceSpan));
|
|
19983
20526
|
break;
|
|
19984
20527
|
case OpKind.DisableBindings:
|
|
19985
20528
|
OpList.replace(op, disableBindings());
|
|
@@ -20016,6 +20559,15 @@ function reifyCreateOperations(unit, ops) {
|
|
|
20016
20559
|
break;
|
|
20017
20560
|
}
|
|
20018
20561
|
break;
|
|
20562
|
+
case OpKind.Defer:
|
|
20563
|
+
OpList.replace(op, defer(op.slot, op.targetSlot, null, op.loading && op.loading.targetSlot, op.placeholder && op.placeholder.targetSlot, op.error && op.error.targetSlot, op.loading?.constIndex ?? null, op.placeholder?.constIndex ?? null, op.sourceSpan));
|
|
20564
|
+
break;
|
|
20565
|
+
case OpKind.DeferSecondaryBlock:
|
|
20566
|
+
OpList.remove(op);
|
|
20567
|
+
break;
|
|
20568
|
+
case OpKind.DeferOn:
|
|
20569
|
+
OpList.replace(op, deferOn(op.sourceSpan));
|
|
20570
|
+
break;
|
|
20019
20571
|
case OpKind.ProjectionDef:
|
|
20020
20572
|
OpList.replace(op, projectionDef(op.def));
|
|
20021
20573
|
break;
|
|
@@ -20075,6 +20627,12 @@ function reifyUpdateOperations(_unit, ops) {
|
|
|
20075
20627
|
OpList.replace(op, classMap(op.expression, op.sourceSpan));
|
|
20076
20628
|
}
|
|
20077
20629
|
break;
|
|
20630
|
+
case OpKind.I18nExpression:
|
|
20631
|
+
OpList.replace(op, i18nExp(op.expression, op.sourceSpan));
|
|
20632
|
+
break;
|
|
20633
|
+
case OpKind.I18nApply:
|
|
20634
|
+
OpList.replace(op, i18nApply(op.targetSlot, op.sourceSpan));
|
|
20635
|
+
break;
|
|
20078
20636
|
case OpKind.InterpolateText:
|
|
20079
20637
|
OpList.replace(op, textInterpolate(op.interpolation.strings, op.interpolation.expressions, op.sourceSpan));
|
|
20080
20638
|
break;
|
|
@@ -20109,10 +20667,10 @@ function reifyUpdateOperations(_unit, ops) {
|
|
|
20109
20667
|
if (op.processed === null) {
|
|
20110
20668
|
throw new Error(`Conditional test was not set.`);
|
|
20111
20669
|
}
|
|
20112
|
-
if (op.
|
|
20670
|
+
if (op.targetSlot === null) {
|
|
20113
20671
|
throw new Error(`Conditional slot was not set.`);
|
|
20114
20672
|
}
|
|
20115
|
-
OpList.replace(op, conditional(op.
|
|
20673
|
+
OpList.replace(op, conditional(op.targetSlot, op.processed, op.contextValue, op.sourceSpan));
|
|
20116
20674
|
break;
|
|
20117
20675
|
case OpKind.Statement:
|
|
20118
20676
|
// Pass statement operations directly through.
|
|
@@ -20130,7 +20688,7 @@ function reifyIrExpression(expr) {
|
|
|
20130
20688
|
case ExpressionKind.NextContext:
|
|
20131
20689
|
return nextContext(expr.steps);
|
|
20132
20690
|
case ExpressionKind.Reference:
|
|
20133
|
-
return reference(expr.
|
|
20691
|
+
return reference(expr.targetSlot + 1 + expr.offset);
|
|
20134
20692
|
case ExpressionKind.LexicalRead:
|
|
20135
20693
|
throw new Error(`AssertionError: unresolved LexicalRead of ${expr.name}`);
|
|
20136
20694
|
case ExpressionKind.RestoreView:
|
|
@@ -20165,13 +20723,13 @@ function reifyIrExpression(expr) {
|
|
|
20165
20723
|
case ExpressionKind.PureFunctionParameterExpr:
|
|
20166
20724
|
throw new Error(`AssertionError: expected PureFunctionParameterExpr to have been extracted`);
|
|
20167
20725
|
case ExpressionKind.PipeBinding:
|
|
20168
|
-
return pipeBind(expr.
|
|
20726
|
+
return pipeBind(expr.targetSlot, expr.varOffset, expr.args);
|
|
20169
20727
|
case ExpressionKind.PipeBindingVariadic:
|
|
20170
|
-
return pipeBindV(expr.
|
|
20728
|
+
return pipeBindV(expr.targetSlot, expr.varOffset, expr.args);
|
|
20171
20729
|
case ExpressionKind.SanitizerExpr:
|
|
20172
20730
|
return importExpr(sanitizerIdentifierMap.get(expr.fn));
|
|
20173
20731
|
case ExpressionKind.SlotLiteralExpr:
|
|
20174
|
-
return literal(expr.
|
|
20732
|
+
return literal(expr.targetSlot);
|
|
20175
20733
|
default:
|
|
20176
20734
|
throw new Error(`AssertionError: Unsupported reification of ir.Expression kind: ${ExpressionKind[expr.kind]}`);
|
|
20177
20735
|
}
|
|
@@ -20290,58 +20848,186 @@ function resolveDollarEvent(unit, ops) {
|
|
|
20290
20848
|
}
|
|
20291
20849
|
}
|
|
20292
20850
|
}
|
|
20293
|
-
|
|
20294
|
-
/**
|
|
20295
|
-
* The escape sequence used indicate message param values.
|
|
20296
|
-
*/
|
|
20297
|
-
const ESCAPE = '\uFFFD';
|
|
20851
|
+
|
|
20852
|
+
/**
|
|
20853
|
+
* The escape sequence used indicate message param values.
|
|
20854
|
+
*/
|
|
20855
|
+
const ESCAPE = '\uFFFD';
|
|
20856
|
+
/**
|
|
20857
|
+
* Marker used to indicate an element tag.
|
|
20858
|
+
*/
|
|
20859
|
+
const ELEMENT_MARKER = '#';
|
|
20860
|
+
/**
|
|
20861
|
+
* Marker used to indicate a template tag.
|
|
20862
|
+
*/
|
|
20863
|
+
const TEMPLATE_MARKER = '*';
|
|
20864
|
+
/**
|
|
20865
|
+
* Marker used to indicate closing of an element or template tag.
|
|
20866
|
+
*/
|
|
20867
|
+
const TAG_CLOSE_MARKER = '/';
|
|
20868
|
+
/**
|
|
20869
|
+
* Marker used to indicate the sub-template context.
|
|
20870
|
+
*/
|
|
20871
|
+
const CONTEXT_MARKER = ':';
|
|
20872
|
+
/**
|
|
20873
|
+
* Marker used to indicate the start of a list of values.
|
|
20874
|
+
*/
|
|
20875
|
+
const LIST_START_MARKER = '[';
|
|
20876
|
+
/**
|
|
20877
|
+
* Marker used to indicate the end of a list of values.
|
|
20878
|
+
*/
|
|
20879
|
+
const LIST_END_MARKER = ']';
|
|
20880
|
+
/**
|
|
20881
|
+
* Delimiter used to separate multiple values in a list.
|
|
20882
|
+
*/
|
|
20883
|
+
const LIST_DELIMITER = '|';
|
|
20884
|
+
var I18nParamValueFlags;
|
|
20885
|
+
(function (I18nParamValueFlags) {
|
|
20886
|
+
I18nParamValueFlags[I18nParamValueFlags["None"] = 0] = "None";
|
|
20887
|
+
/**
|
|
20888
|
+
* This value represtents an element tag.
|
|
20889
|
+
*/
|
|
20890
|
+
I18nParamValueFlags[I18nParamValueFlags["ElementTag"] = 1] = "ElementTag";
|
|
20891
|
+
/**
|
|
20892
|
+
* This value represents a template tag.
|
|
20893
|
+
*/
|
|
20894
|
+
I18nParamValueFlags[I18nParamValueFlags["TemplateTag"] = 2] = "TemplateTag";
|
|
20895
|
+
/**
|
|
20896
|
+
* This value represents the closing of a tag. (Can only be used together with ElementTag or
|
|
20897
|
+
* TemplateTag)
|
|
20898
|
+
*/
|
|
20899
|
+
I18nParamValueFlags[I18nParamValueFlags["CloseTag"] = 4] = "CloseTag";
|
|
20900
|
+
})(I18nParamValueFlags || (I18nParamValueFlags = {}));
|
|
20901
|
+
/**
|
|
20902
|
+
* Represents the complete i18n params map for an i18n op.
|
|
20903
|
+
*/
|
|
20904
|
+
class I18nPlaceholderParams {
|
|
20905
|
+
constructor() {
|
|
20906
|
+
this.values = new Map();
|
|
20907
|
+
}
|
|
20908
|
+
/**
|
|
20909
|
+
* Adds a new value to the params map.
|
|
20910
|
+
*/
|
|
20911
|
+
addValue(placeholder, value, subTemplateIndex, flags) {
|
|
20912
|
+
const placeholderValues = this.values.get(placeholder) ?? [];
|
|
20913
|
+
placeholderValues.push({ value, subTemplateIndex, flags });
|
|
20914
|
+
this.values.set(placeholder, placeholderValues);
|
|
20915
|
+
}
|
|
20916
|
+
/**
|
|
20917
|
+
* Saves the params map, in serialized form, into the given i18n op.
|
|
20918
|
+
*/
|
|
20919
|
+
saveToOp(op) {
|
|
20920
|
+
for (const [placeholder, placeholderValues] of this.values) {
|
|
20921
|
+
op.params.set(placeholder, literal(this.serializeValues(placeholderValues)));
|
|
20922
|
+
}
|
|
20923
|
+
}
|
|
20924
|
+
/**
|
|
20925
|
+
* Serializes a list of i18n placeholder values.
|
|
20926
|
+
*/
|
|
20927
|
+
serializeValues(values) {
|
|
20928
|
+
const serializedValues = values.map(value => this.serializeValue(value));
|
|
20929
|
+
return serializedValues.length === 1 ?
|
|
20930
|
+
serializedValues[0] :
|
|
20931
|
+
`${LIST_START_MARKER}${serializedValues.join(LIST_DELIMITER)}${LIST_END_MARKER}`;
|
|
20932
|
+
}
|
|
20933
|
+
/**
|
|
20934
|
+
* Serializes a single i18n placeholder value.
|
|
20935
|
+
*/
|
|
20936
|
+
serializeValue(value) {
|
|
20937
|
+
let tagMarker = '';
|
|
20938
|
+
let closeMarker = '';
|
|
20939
|
+
if (value.flags & I18nParamValueFlags.ElementTag) {
|
|
20940
|
+
tagMarker = ELEMENT_MARKER;
|
|
20941
|
+
}
|
|
20942
|
+
else if (value.flags & I18nParamValueFlags.TemplateTag) {
|
|
20943
|
+
tagMarker = TEMPLATE_MARKER;
|
|
20944
|
+
}
|
|
20945
|
+
if (tagMarker !== '') {
|
|
20946
|
+
closeMarker = value.flags & I18nParamValueFlags.CloseTag ? TAG_CLOSE_MARKER : '';
|
|
20947
|
+
}
|
|
20948
|
+
const context = value.subTemplateIndex === null ? '' : `${CONTEXT_MARKER}${value.subTemplateIndex}`;
|
|
20949
|
+
return `${ESCAPE}${closeMarker}${tagMarker}${value.value}${context}${ESCAPE}`;
|
|
20950
|
+
}
|
|
20951
|
+
}
|
|
20298
20952
|
/**
|
|
20299
20953
|
* Resolve the placeholders in i18n messages.
|
|
20300
20954
|
*/
|
|
20301
20955
|
function phaseResolveI18nPlaceholders(job) {
|
|
20302
20956
|
for (const unit of job.units) {
|
|
20303
|
-
|
|
20304
|
-
|
|
20305
|
-
let
|
|
20957
|
+
const i18nOps = new Map();
|
|
20958
|
+
const params = new Map();
|
|
20959
|
+
let currentI18nOp = null;
|
|
20960
|
+
// Record slots for tag name placeholders.
|
|
20306
20961
|
for (const op of unit.create) {
|
|
20307
|
-
|
|
20308
|
-
|
|
20309
|
-
|
|
20310
|
-
|
|
20311
|
-
|
|
20962
|
+
switch (op.kind) {
|
|
20963
|
+
case OpKind.I18nStart:
|
|
20964
|
+
case OpKind.I18n:
|
|
20965
|
+
i18nOps.set(op.xref, op);
|
|
20966
|
+
currentI18nOp = op.kind === OpKind.I18nStart ? op : null;
|
|
20967
|
+
break;
|
|
20968
|
+
case OpKind.I18nEnd:
|
|
20969
|
+
currentI18nOp = null;
|
|
20970
|
+
break;
|
|
20971
|
+
case OpKind.Element:
|
|
20972
|
+
case OpKind.ElementStart:
|
|
20973
|
+
case OpKind.Template:
|
|
20974
|
+
// For elements with i18n placeholders, record its slot value in the params map under both
|
|
20975
|
+
// the start and close placeholders.
|
|
20976
|
+
if (op.i18nPlaceholder !== undefined) {
|
|
20977
|
+
if (currentI18nOp === null) {
|
|
20978
|
+
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
20979
|
+
}
|
|
20980
|
+
const { startName, closeName } = op.i18nPlaceholder;
|
|
20981
|
+
const subTemplateIndex = getSubTemplateIndexForTag(job, currentI18nOp, op);
|
|
20982
|
+
const flags = op.kind === OpKind.Template ? I18nParamValueFlags.TemplateTag :
|
|
20983
|
+
I18nParamValueFlags.ElementTag;
|
|
20984
|
+
addParam(params, currentI18nOp, startName, op.slot, subTemplateIndex, flags);
|
|
20985
|
+
addParam(params, currentI18nOp, closeName, op.slot, subTemplateIndex, flags | I18nParamValueFlags.CloseTag);
|
|
20986
|
+
}
|
|
20987
|
+
break;
|
|
20312
20988
|
}
|
|
20313
|
-
|
|
20314
|
-
|
|
20315
|
-
|
|
20316
|
-
|
|
20989
|
+
}
|
|
20990
|
+
// Fill in values for each of the i18n expression placeholders.
|
|
20991
|
+
const i18nBlockPlaceholderIndices = new Map();
|
|
20992
|
+
for (const op of unit.update) {
|
|
20993
|
+
if (op.kind === OpKind.I18nExpression) {
|
|
20994
|
+
const i18nOp = i18nOps.get(op.owner);
|
|
20995
|
+
let index = i18nBlockPlaceholderIndices.get(op.owner) || 0;
|
|
20996
|
+
if (!i18nOp) {
|
|
20997
|
+
throw Error('Cannot find corresponding i18nStart for i18nExpr');
|
|
20317
20998
|
}
|
|
20318
|
-
|
|
20319
|
-
|
|
20320
|
-
// TODO: when TemplateDefinitionBuilder compatibility is not required, we can just add both
|
|
20321
|
-
// keys directly to the map here.
|
|
20322
|
-
startTags.push({
|
|
20323
|
-
i18nOp,
|
|
20324
|
-
placeholder: op.i18n.startName,
|
|
20325
|
-
value: literal(`${ESCAPE}#${op.slot}${ESCAPE}`)
|
|
20326
|
-
});
|
|
20327
|
-
closeTags.push({
|
|
20328
|
-
i18nOp,
|
|
20329
|
-
placeholder: op.i18n.closeName,
|
|
20330
|
-
value: literal(`${ESCAPE}/#${op.slot}${ESCAPE}`)
|
|
20331
|
-
});
|
|
20999
|
+
addParam(params, i18nOp, op.i18nPlaceholder.name, index++, i18nOp.subTemplateIndex);
|
|
21000
|
+
i18nBlockPlaceholderIndices.set(op.owner, index);
|
|
20332
21001
|
}
|
|
20333
21002
|
}
|
|
20334
|
-
//
|
|
20335
|
-
for (const
|
|
20336
|
-
|
|
21003
|
+
// After colleccting all params, save them to the i18n ops.
|
|
21004
|
+
for (const [xref, i18nOpParams] of params) {
|
|
21005
|
+
i18nOpParams.saveToOp(i18nOps.get(xref));
|
|
20337
21006
|
}
|
|
20338
|
-
|
|
20339
|
-
|
|
20340
|
-
|
|
20341
|
-
|
|
20342
|
-
|
|
21007
|
+
}
|
|
21008
|
+
}
|
|
21009
|
+
/**
|
|
21010
|
+
* Add a param to the params map for the given i18n op.
|
|
21011
|
+
*/
|
|
21012
|
+
function addParam(params, i18nOp, placeholder, value, subTemplateIndex, flags = I18nParamValueFlags.None) {
|
|
21013
|
+
const i18nOpParams = params.get(i18nOp.xref) ?? new I18nPlaceholderParams();
|
|
21014
|
+
i18nOpParams.addValue(placeholder, value, subTemplateIndex, flags);
|
|
21015
|
+
params.set(i18nOp.xref, i18nOpParams);
|
|
21016
|
+
}
|
|
21017
|
+
/**
|
|
21018
|
+
* Get the subTemplateIndex for the given op. For template ops, use the subTemplateIndex of the
|
|
21019
|
+
* child i18n block inside the template. For all other ops, use the subTemplateIndex of the i18n
|
|
21020
|
+
* block the op belongs to.
|
|
21021
|
+
*/
|
|
21022
|
+
function getSubTemplateIndexForTag(job, i18nOp, op) {
|
|
21023
|
+
if (op.kind === OpKind.Template) {
|
|
21024
|
+
for (const childOp of job.views.get(op.xref).create) {
|
|
21025
|
+
if (childOp.kind === OpKind.I18nStart) {
|
|
21026
|
+
return childOp.subTemplateIndex;
|
|
21027
|
+
}
|
|
20343
21028
|
}
|
|
20344
21029
|
}
|
|
21030
|
+
return i18nOp.subTemplateIndex;
|
|
20345
21031
|
}
|
|
20346
21032
|
|
|
20347
21033
|
/**
|
|
@@ -20586,19 +21272,19 @@ function phaseSlotAllocation(job) {
|
|
|
20586
21272
|
const childView = job.views.get(op.xref);
|
|
20587
21273
|
op.decls = childView.decls;
|
|
20588
21274
|
}
|
|
20589
|
-
if (hasUsesSlotIndexTrait(op) && op.
|
|
21275
|
+
if (hasUsesSlotIndexTrait(op) && op.targetSlot === null) {
|
|
20590
21276
|
if (!slotMap.has(op.target)) {
|
|
20591
21277
|
// We do expect to find a slot allocated for everything which might be referenced.
|
|
20592
21278
|
throw new Error(`AssertionError: no slot allocated for ${OpKind[op.kind]} target ${op.target}`);
|
|
20593
21279
|
}
|
|
20594
|
-
op.
|
|
21280
|
+
op.targetSlot = slotMap.get(op.target);
|
|
20595
21281
|
}
|
|
20596
21282
|
// Process all `ir.Expression`s within this view, and look for `usesSlotIndexExprTrait`.
|
|
20597
21283
|
visitExpressionsInOp(op, expr => {
|
|
20598
21284
|
if (!isIrExpression(expr)) {
|
|
20599
21285
|
return;
|
|
20600
21286
|
}
|
|
20601
|
-
if (!hasUsesSlotIndexTrait(expr) || expr.
|
|
21287
|
+
if (!hasUsesSlotIndexTrait(expr) || expr.targetSlot !== null) {
|
|
20602
21288
|
return;
|
|
20603
21289
|
}
|
|
20604
21290
|
// The `UsesSlotIndexExprTrait` indicates that this expression references something declared
|
|
@@ -20609,7 +21295,7 @@ function phaseSlotAllocation(job) {
|
|
|
20609
21295
|
throw new Error(`AssertionError: no slot allocated for ${expr.constructor.name} target ${expr.target}`);
|
|
20610
21296
|
}
|
|
20611
21297
|
// Record the allocated slot on the expression.
|
|
20612
|
-
expr.
|
|
21298
|
+
expr.targetSlot = slotMap.get(expr.target);
|
|
20613
21299
|
});
|
|
20614
21300
|
}
|
|
20615
21301
|
}
|
|
@@ -20660,47 +21346,62 @@ function phaseStyleBindingSpecialization(cpl) {
|
|
|
20660
21346
|
*/
|
|
20661
21347
|
function phaseTemporaryVariables(cpl) {
|
|
20662
21348
|
for (const unit of cpl.units) {
|
|
20663
|
-
|
|
20664
|
-
|
|
20665
|
-
|
|
20666
|
-
|
|
20667
|
-
|
|
20668
|
-
|
|
20669
|
-
|
|
20670
|
-
|
|
20671
|
-
|
|
20672
|
-
|
|
20673
|
-
|
|
20674
|
-
|
|
20675
|
-
|
|
20676
|
-
|
|
20677
|
-
|
|
20678
|
-
|
|
20679
|
-
|
|
20680
|
-
|
|
20681
|
-
|
|
20682
|
-
|
|
20683
|
-
|
|
20684
|
-
|
|
20685
|
-
|
|
20686
|
-
|
|
20687
|
-
|
|
21349
|
+
unit.create.prepend(generateTemporaries(unit.create));
|
|
21350
|
+
unit.update.prepend(generateTemporaries(unit.update));
|
|
21351
|
+
}
|
|
21352
|
+
}
|
|
21353
|
+
function generateTemporaries(ops) {
|
|
21354
|
+
let opCount = 0;
|
|
21355
|
+
let generatedStatements = [];
|
|
21356
|
+
// For each op, search for any variables that are assigned or read. For each variable, generate a
|
|
21357
|
+
// name and produce a `DeclareVarStmt` to the beginning of the block.
|
|
21358
|
+
for (const op of ops) {
|
|
21359
|
+
// Identify the final time each temp var is read.
|
|
21360
|
+
const finalReads = new Map();
|
|
21361
|
+
visitExpressionsInOp(op, (expr, flag) => {
|
|
21362
|
+
if (flag & VisitorContextFlag.InChildOperation) {
|
|
21363
|
+
return;
|
|
21364
|
+
}
|
|
21365
|
+
if (expr instanceof ReadTemporaryExpr) {
|
|
21366
|
+
finalReads.set(expr.xref, expr);
|
|
21367
|
+
}
|
|
21368
|
+
});
|
|
21369
|
+
// Name the temp vars, accounting for the fact that a name can be reused after it has been
|
|
21370
|
+
// read for the final time.
|
|
21371
|
+
let count = 0;
|
|
21372
|
+
const assigned = new Set();
|
|
21373
|
+
const released = new Set();
|
|
21374
|
+
const defs = new Map();
|
|
21375
|
+
visitExpressionsInOp(op, (expr, flag) => {
|
|
21376
|
+
if (flag & VisitorContextFlag.InChildOperation) {
|
|
21377
|
+
return;
|
|
21378
|
+
}
|
|
21379
|
+
if (expr instanceof AssignTemporaryExpr) {
|
|
21380
|
+
if (!assigned.has(expr.xref)) {
|
|
21381
|
+
assigned.add(expr.xref);
|
|
21382
|
+
// TODO: Exactly replicate the naming scheme used by `TemplateDefinitionBuilder`.
|
|
21383
|
+
// It seems to rely on an expression index instead of an op index.
|
|
21384
|
+
defs.set(expr.xref, `tmp_${opCount}_${count++}`);
|
|
20688
21385
|
}
|
|
20689
|
-
|
|
20690
|
-
|
|
20691
|
-
|
|
20692
|
-
|
|
20693
|
-
|
|
20694
|
-
|
|
21386
|
+
assignName(defs, expr);
|
|
21387
|
+
}
|
|
21388
|
+
else if (expr instanceof ReadTemporaryExpr) {
|
|
21389
|
+
if (finalReads.get(expr.xref) === expr) {
|
|
21390
|
+
released.add(expr.xref);
|
|
21391
|
+
count--;
|
|
20695
21392
|
}
|
|
20696
|
-
|
|
20697
|
-
|
|
20698
|
-
|
|
20699
|
-
|
|
20700
|
-
|
|
21393
|
+
assignName(defs, expr);
|
|
21394
|
+
}
|
|
21395
|
+
});
|
|
21396
|
+
// Add declarations for the temp vars.
|
|
21397
|
+
generatedStatements.push(...Array.from(new Set(defs.values()))
|
|
21398
|
+
.map(name => createStatementOp(new DeclareVarStmt(name))));
|
|
21399
|
+
opCount++;
|
|
21400
|
+
if (op.kind === OpKind.Listener) {
|
|
21401
|
+
op.handlerOps.prepend(generateTemporaries(op.handlerOps));
|
|
20701
21402
|
}
|
|
20702
|
-
unit.update.prepend(generatedStatements);
|
|
20703
21403
|
}
|
|
21404
|
+
return generatedStatements;
|
|
20704
21405
|
}
|
|
20705
21406
|
/**
|
|
20706
21407
|
* Assigns a name to the temporary variable in the given temporary variable expression.
|
|
@@ -21068,6 +21769,13 @@ function allowConservativeInlining(decl, target) {
|
|
|
21068
21769
|
// that behavior here.
|
|
21069
21770
|
switch (decl.variable.kind) {
|
|
21070
21771
|
case SemanticVariableKind.Identifier:
|
|
21772
|
+
if (decl.initializer instanceof ReadVarExpr && decl.initializer.name === 'ctx') {
|
|
21773
|
+
// Although TemplateDefinitionBuilder is cautious about inlining, we still want to do so
|
|
21774
|
+
// when the variable is the context, to imitate its behavior with aliases in control flow
|
|
21775
|
+
// blocks. This quirky behavior will become dead code once compatibility mode is no longer
|
|
21776
|
+
// supported.
|
|
21777
|
+
return true;
|
|
21778
|
+
}
|
|
21071
21779
|
return false;
|
|
21072
21780
|
case SemanticVariableKind.Context:
|
|
21073
21781
|
// Context can only be inlined into other variables.
|
|
@@ -21077,111 +21785,20 @@ function allowConservativeInlining(decl, target) {
|
|
|
21077
21785
|
}
|
|
21078
21786
|
}
|
|
21079
21787
|
|
|
21080
|
-
/**
|
|
21081
|
-
* Locate projection slots, populate the each component's `ngContentSelectors` literal field,
|
|
21082
|
-
* populate `project` arguments, and generate the required `projectionDef` instruction for the job's
|
|
21083
|
-
* root view.
|
|
21084
|
-
*/
|
|
21085
|
-
function phaseGenerateProjectionDef(job) {
|
|
21086
|
-
// TODO: Why does TemplateDefinitionBuilder force a shared constant?
|
|
21087
|
-
const share = job.compatibility === CompatibilityMode.TemplateDefinitionBuilder;
|
|
21088
|
-
// Collect all selectors from this component, and its nested views. Also, assign each projection a
|
|
21089
|
-
// unique ascending projection slot index.
|
|
21090
|
-
const selectors = [];
|
|
21091
|
-
let projectionSlotIndex = 0;
|
|
21092
|
-
for (const unit of job.units) {
|
|
21093
|
-
for (const op of unit.create) {
|
|
21094
|
-
if (op.kind === OpKind.Projection) {
|
|
21095
|
-
selectors.push(op.selector);
|
|
21096
|
-
op.projectionSlotIndex = projectionSlotIndex++;
|
|
21097
|
-
}
|
|
21098
|
-
}
|
|
21099
|
-
}
|
|
21100
|
-
if (selectors.length > 0) {
|
|
21101
|
-
// Create the projectionDef array. If we only found a single wildcard selector, then we use the
|
|
21102
|
-
// default behavior with no arguments instead.
|
|
21103
|
-
let defExpr = null;
|
|
21104
|
-
if (selectors.length > 1 || selectors[0] !== '*') {
|
|
21105
|
-
const def = selectors.map(s => s === '*' ? s : parseSelectorToR3Selector(s));
|
|
21106
|
-
defExpr = job.pool.getConstLiteral(literalOrArrayLiteral(def), share);
|
|
21107
|
-
}
|
|
21108
|
-
// Create the ngContentSelectors constant.
|
|
21109
|
-
job.contentSelectors = job.pool.getConstLiteral(literalOrArrayLiteral(selectors), share);
|
|
21110
|
-
// The projection def instruction goes at the beginning of the root view, before any
|
|
21111
|
-
// `projection` instructions.
|
|
21112
|
-
job.root.create.prepend([createProjectionDefOp(defExpr)]);
|
|
21113
|
-
}
|
|
21114
|
-
}
|
|
21115
|
-
|
|
21116
|
-
/**
|
|
21117
|
-
* Lifts i18n properties into the consts array.
|
|
21118
|
-
*/
|
|
21119
|
-
function phaseI18nConstCollection(job) {
|
|
21120
|
-
// Serialize the extracted messages into the const array.
|
|
21121
|
-
// TODO: Use `Map` instead of object.
|
|
21122
|
-
const messageConstIndices = {};
|
|
21123
|
-
for (const unit of job.units) {
|
|
21124
|
-
for (const op of unit.create) {
|
|
21125
|
-
if (op.kind === OpKind.ExtractedMessage) {
|
|
21126
|
-
messageConstIndices[op.owner] = job.addConst(op.expression, op.statements);
|
|
21127
|
-
OpList.remove(op);
|
|
21128
|
-
}
|
|
21129
|
-
}
|
|
21130
|
-
}
|
|
21131
|
-
// Assign const index to i18n ops that messages were extracted from.
|
|
21132
|
-
for (const unit of job.units) {
|
|
21133
|
-
for (const op of unit.create) {
|
|
21134
|
-
if (op.kind === OpKind.I18nStart && messageConstIndices[op.xref] !== undefined) {
|
|
21135
|
-
op.messageIndex = messageConstIndices[op.xref];
|
|
21136
|
-
}
|
|
21137
|
-
}
|
|
21138
|
-
}
|
|
21139
|
-
}
|
|
21140
|
-
|
|
21141
|
-
/**
|
|
21142
|
-
* Attributes of `ng-content` named 'select' are specifically removed, because they control which
|
|
21143
|
-
* content matches as a property of the `projection`, and are not a plain attribute.
|
|
21144
|
-
*/
|
|
21145
|
-
function phaseRemoveContentSelectors(job) {
|
|
21146
|
-
for (const unit of job.units) {
|
|
21147
|
-
const elements = getElementsByXrefId(unit);
|
|
21148
|
-
for (const op of unit.update) {
|
|
21149
|
-
switch (op.kind) {
|
|
21150
|
-
case OpKind.Binding:
|
|
21151
|
-
const target = lookupElement(elements, op.target);
|
|
21152
|
-
if (op.name.toLowerCase() === 'select' && target.kind === OpKind.Projection) {
|
|
21153
|
-
OpList.remove(op);
|
|
21154
|
-
}
|
|
21155
|
-
continue;
|
|
21156
|
-
}
|
|
21157
|
-
}
|
|
21158
|
-
}
|
|
21159
|
-
}
|
|
21160
|
-
/**
|
|
21161
|
-
* Looks up an element in the given map by xref ID.
|
|
21162
|
-
*/
|
|
21163
|
-
function lookupElement(elements, xref) {
|
|
21164
|
-
const el = elements.get(xref);
|
|
21165
|
-
if (el === undefined) {
|
|
21166
|
-
throw new Error('All attributes should have an element-like target.');
|
|
21167
|
-
}
|
|
21168
|
-
return el;
|
|
21169
|
-
}
|
|
21170
|
-
|
|
21171
21788
|
const phases = [
|
|
21172
21789
|
{ kind: CompilationJobKind.Tmpl, fn: phaseRemoveContentSelectors },
|
|
21173
|
-
{ kind: CompilationJobKind.Tmpl, fn: phaseGenerateI18nBlocks },
|
|
21174
|
-
{ kind: CompilationJobKind.Tmpl, fn: phaseI18nTextExtraction },
|
|
21175
21790
|
{ kind: CompilationJobKind.Host, fn: phaseHostStylePropertyParsing },
|
|
21176
21791
|
{ kind: CompilationJobKind.Tmpl, fn: phaseNamespace },
|
|
21177
21792
|
{ kind: CompilationJobKind.Both, fn: phaseStyleBindingSpecialization },
|
|
21178
21793
|
{ kind: CompilationJobKind.Both, fn: phaseBindingSpecialization },
|
|
21794
|
+
{ kind: CompilationJobKind.Tmpl, fn: phasePropagateI18nBlocks },
|
|
21179
21795
|
{ kind: CompilationJobKind.Both, fn: phaseAttributeExtraction },
|
|
21180
21796
|
{ kind: CompilationJobKind.Both, fn: phaseParseExtractedStyles },
|
|
21181
21797
|
{ kind: CompilationJobKind.Tmpl, fn: phaseRemoveEmptyBindings },
|
|
21182
21798
|
{ kind: CompilationJobKind.Tmpl, fn: phaseConditionals },
|
|
21183
|
-
{ kind: CompilationJobKind.Tmpl, fn: phaseNoListenersOnTemplates },
|
|
21184
21799
|
{ kind: CompilationJobKind.Tmpl, fn: phasePipeCreation },
|
|
21800
|
+
{ kind: CompilationJobKind.Tmpl, fn: phaseI18nTextExtraction },
|
|
21801
|
+
{ kind: CompilationJobKind.Tmpl, fn: phaseApplyI18nExpressions },
|
|
21185
21802
|
{ kind: CompilationJobKind.Tmpl, fn: phasePipeVariadic },
|
|
21186
21803
|
{ kind: CompilationJobKind.Both, fn: phasePureLiteralStructures },
|
|
21187
21804
|
{ kind: CompilationJobKind.Tmpl, fn: phaseGenerateProjectionDef },
|
|
@@ -21198,9 +21815,12 @@ const phases = [
|
|
|
21198
21815
|
{ kind: CompilationJobKind.Both, fn: phaseTemporaryVariables },
|
|
21199
21816
|
{ kind: CompilationJobKind.Tmpl, fn: phaseSlotAllocation },
|
|
21200
21817
|
{ kind: CompilationJobKind.Tmpl, fn: phaseResolveI18nPlaceholders },
|
|
21818
|
+
{ kind: CompilationJobKind.Tmpl, fn: phasePropagateI18nPlaceholders },
|
|
21201
21819
|
{ kind: CompilationJobKind.Tmpl, fn: phaseI18nMessageExtraction },
|
|
21202
21820
|
{ kind: CompilationJobKind.Tmpl, fn: phaseI18nConstCollection },
|
|
21821
|
+
{ kind: CompilationJobKind.Tmpl, fn: phaseConstTraitCollection },
|
|
21203
21822
|
{ kind: CompilationJobKind.Both, fn: phaseConstCollection },
|
|
21823
|
+
{ kind: CompilationJobKind.Tmpl, fn: phaseAssignI18nSlotDependencies },
|
|
21204
21824
|
{ kind: CompilationJobKind.Both, fn: phaseVarCounting },
|
|
21205
21825
|
{ kind: CompilationJobKind.Tmpl, fn: phaseGenerateAdvance },
|
|
21206
21826
|
{ kind: CompilationJobKind.Both, fn: phaseVariableOptimization },
|
|
@@ -21404,9 +22024,15 @@ function ingestNodes(unit, template) {
|
|
|
21404
22024
|
else if (node instanceof BoundText) {
|
|
21405
22025
|
ingestBoundText(unit, node);
|
|
21406
22026
|
}
|
|
22027
|
+
else if (node instanceof IfBlock) {
|
|
22028
|
+
ingestIfBlock(unit, node);
|
|
22029
|
+
}
|
|
21407
22030
|
else if (node instanceof SwitchBlock) {
|
|
21408
22031
|
ingestSwitchBlock(unit, node);
|
|
21409
22032
|
}
|
|
22033
|
+
else if (node instanceof DeferredBlock) {
|
|
22034
|
+
ingestDeferBlock(unit, node);
|
|
22035
|
+
}
|
|
21410
22036
|
else {
|
|
21411
22037
|
throw new Error(`Unsupported template node: ${node.constructor.name}`);
|
|
21412
22038
|
}
|
|
@@ -21416,31 +22042,47 @@ function ingestNodes(unit, template) {
|
|
|
21416
22042
|
* Ingest an element AST from the template into the given `ViewCompilation`.
|
|
21417
22043
|
*/
|
|
21418
22044
|
function ingestElement(unit, element) {
|
|
22045
|
+
if (element.i18n !== undefined &&
|
|
22046
|
+
!(element.i18n instanceof Message || element.i18n instanceof TagPlaceholder)) {
|
|
22047
|
+
throw Error(`Unhandled i18n metadata type for element: ${element.i18n.constructor.name}`);
|
|
22048
|
+
}
|
|
21419
22049
|
const staticAttributes = {};
|
|
21420
22050
|
for (const attr of element.attributes) {
|
|
21421
22051
|
staticAttributes[attr.name] = attr.value;
|
|
21422
22052
|
}
|
|
21423
22053
|
const id = unit.job.allocateXrefId();
|
|
21424
22054
|
const [namespaceKey, elementName] = splitNsName(element.name);
|
|
21425
|
-
const startOp = createElementStartOp(elementName, id, namespaceForKey(namespaceKey), element.i18n, element.startSourceSpan);
|
|
22055
|
+
const startOp = createElementStartOp(elementName, id, namespaceForKey(namespaceKey), element.i18n instanceof TagPlaceholder ? element.i18n : undefined, element.startSourceSpan);
|
|
21426
22056
|
unit.create.push(startOp);
|
|
21427
22057
|
ingestBindings(unit, startOp, element);
|
|
21428
22058
|
ingestReferences(startOp, element);
|
|
21429
22059
|
ingestNodes(unit, element.children);
|
|
21430
|
-
|
|
22060
|
+
const endOp = createElementEndOp(id, element.endSourceSpan);
|
|
22061
|
+
unit.create.push(endOp);
|
|
22062
|
+
// If there is an i18n message associated with this element, insert i18n start and end ops.
|
|
22063
|
+
if (element.i18n instanceof Message) {
|
|
22064
|
+
const i18nBlockId = unit.job.allocateXrefId();
|
|
22065
|
+
OpList.insertAfter(createI18nStartOp(i18nBlockId, element.i18n), startOp);
|
|
22066
|
+
OpList.insertBefore(createI18nEndOp(i18nBlockId), endOp);
|
|
22067
|
+
}
|
|
21431
22068
|
}
|
|
21432
22069
|
/**
|
|
21433
22070
|
* Ingest an `ng-template` node from the AST into the given `ViewCompilation`.
|
|
21434
22071
|
*/
|
|
21435
22072
|
function ingestTemplate(unit, tmpl) {
|
|
22073
|
+
if (tmpl.i18n !== undefined &&
|
|
22074
|
+
!(tmpl.i18n instanceof Message || tmpl.i18n instanceof TagPlaceholder)) {
|
|
22075
|
+
throw Error(`Unhandled i18n metadata type for template: ${tmpl.i18n.constructor.name}`);
|
|
22076
|
+
}
|
|
21436
22077
|
const childView = unit.job.allocateView(unit.xref);
|
|
21437
22078
|
let tagNameWithoutNamespace = tmpl.tagName;
|
|
21438
22079
|
let namespacePrefix = '';
|
|
21439
22080
|
if (tmpl.tagName) {
|
|
21440
22081
|
[namespacePrefix, tagNameWithoutNamespace] = splitNsName(tmpl.tagName);
|
|
21441
22082
|
}
|
|
22083
|
+
const i18nPlaceholder = tmpl.i18n instanceof TagPlaceholder ? tmpl.i18n : undefined;
|
|
21442
22084
|
// TODO: validate the fallback tag name here.
|
|
21443
|
-
const tplOp = createTemplateOp(childView.xref, tagNameWithoutNamespace ?? 'ng-template', namespaceForKey(namespacePrefix), false,
|
|
22085
|
+
const tplOp = createTemplateOp(childView.xref, tagNameWithoutNamespace ?? 'ng-template', namespaceForKey(namespacePrefix), false, i18nPlaceholder, tmpl.startSourceSpan);
|
|
21444
22086
|
unit.create.push(tplOp);
|
|
21445
22087
|
ingestBindings(unit, tplOp, tmpl);
|
|
21446
22088
|
ingestReferences(tplOp, tmpl);
|
|
@@ -21448,6 +22090,12 @@ function ingestTemplate(unit, tmpl) {
|
|
|
21448
22090
|
for (const { name, value } of tmpl.variables) {
|
|
21449
22091
|
childView.contextVariables.set(name, value);
|
|
21450
22092
|
}
|
|
22093
|
+
// If there is an i18n message associated with this template, insert i18n start and end ops.
|
|
22094
|
+
if (tmpl.i18n instanceof Message) {
|
|
22095
|
+
const id = unit.job.allocateXrefId();
|
|
22096
|
+
OpList.insertAfter(createI18nStartOp(id, tmpl.i18n), childView.create.head);
|
|
22097
|
+
OpList.insertBefore(createI18nEndOp(id), childView.create.tail);
|
|
22098
|
+
}
|
|
21451
22099
|
}
|
|
21452
22100
|
/**
|
|
21453
22101
|
* Ingest a literal text node from the AST into the given `ViewCompilation`.
|
|
@@ -21455,7 +22103,7 @@ function ingestTemplate(unit, tmpl) {
|
|
|
21455
22103
|
function ingestContent(unit, content) {
|
|
21456
22104
|
const op = createProjectionOp(unit.job.allocateXrefId(), content.selector);
|
|
21457
22105
|
for (const attr of content.attributes) {
|
|
21458
|
-
ingestBinding(unit, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan,
|
|
22106
|
+
ingestBinding(unit, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, BindingFlags.TextValue);
|
|
21459
22107
|
}
|
|
21460
22108
|
unit.create.push(op);
|
|
21461
22109
|
}
|
|
@@ -21476,35 +22124,109 @@ function ingestBoundText(unit, text) {
|
|
|
21476
22124
|
if (!(value instanceof Interpolation$1)) {
|
|
21477
22125
|
throw new Error(`AssertionError: expected Interpolation for BoundText node, got ${value.constructor.name}`);
|
|
21478
22126
|
}
|
|
22127
|
+
if (text.i18n !== undefined && !(text.i18n instanceof Container)) {
|
|
22128
|
+
throw Error(`Unhandled i18n metadata type for text interpolation: ${text.i18n?.constructor.name}`);
|
|
22129
|
+
}
|
|
22130
|
+
const i18nPlaceholders = text.i18n instanceof Container ?
|
|
22131
|
+
text.i18n.children.filter((node) => node instanceof Placeholder) :
|
|
22132
|
+
[];
|
|
21479
22133
|
const textXref = unit.job.allocateXrefId();
|
|
21480
22134
|
unit.create.push(createTextOp(textXref, '', text.sourceSpan));
|
|
21481
22135
|
// TemplateDefinitionBuilder does not generate source maps for sub-expressions inside an
|
|
21482
22136
|
// interpolation. We copy that behavior in compatibility mode.
|
|
21483
22137
|
// TODO: is it actually correct to generate these extra maps in modern mode?
|
|
21484
22138
|
const baseSourceSpan = unit.job.compatibility ? null : text.sourceSpan;
|
|
21485
|
-
unit.update.push(createInterpolateTextOp(textXref, new Interpolation(value.strings, value.expressions.map(expr => convertAst(expr, unit.job, baseSourceSpan))), text.sourceSpan));
|
|
22139
|
+
unit.update.push(createInterpolateTextOp(textXref, new Interpolation(value.strings, value.expressions.map(expr => convertAst(expr, unit.job, baseSourceSpan))), i18nPlaceholders, text.sourceSpan));
|
|
22140
|
+
}
|
|
22141
|
+
/**
|
|
22142
|
+
* Ingest an `@if` block into the given `ViewCompilation`.
|
|
22143
|
+
*/
|
|
22144
|
+
function ingestIfBlock(unit, ifBlock) {
|
|
22145
|
+
let firstXref = null;
|
|
22146
|
+
let conditions = [];
|
|
22147
|
+
for (const ifCase of ifBlock.branches) {
|
|
22148
|
+
const cView = unit.job.allocateView(unit.xref);
|
|
22149
|
+
if (ifCase.expressionAlias !== null) {
|
|
22150
|
+
cView.contextVariables.set(ifCase.expressionAlias.name, CTX_REF);
|
|
22151
|
+
}
|
|
22152
|
+
if (firstXref === null) {
|
|
22153
|
+
firstXref = cView.xref;
|
|
22154
|
+
}
|
|
22155
|
+
unit.create.push(createTemplateOp(cView.xref, 'Conditional', Namespace.HTML, true, undefined /* TODO: figure out how i18n works with new control flow */, ifCase.sourceSpan));
|
|
22156
|
+
const caseExpr = ifCase.expression ? convertAst(ifCase.expression, unit.job, null) : null;
|
|
22157
|
+
const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr, cView.xref, ifCase.expressionAlias);
|
|
22158
|
+
conditions.push(conditionalCaseExpr);
|
|
22159
|
+
ingestNodes(cView, ifCase.children);
|
|
22160
|
+
}
|
|
22161
|
+
const conditional = createConditionalOp(firstXref, null, conditions, ifBlock.sourceSpan);
|
|
22162
|
+
unit.update.push(conditional);
|
|
21486
22163
|
}
|
|
21487
22164
|
/**
|
|
21488
|
-
* Ingest
|
|
22165
|
+
* Ingest an `@switch` block into the given `ViewCompilation`.
|
|
21489
22166
|
*/
|
|
21490
22167
|
function ingestSwitchBlock(unit, switchBlock) {
|
|
21491
22168
|
let firstXref = null;
|
|
21492
22169
|
let conditions = [];
|
|
21493
22170
|
for (const switchCase of switchBlock.cases) {
|
|
21494
22171
|
const cView = unit.job.allocateView(unit.xref);
|
|
21495
|
-
if (
|
|
22172
|
+
if (firstXref === null) {
|
|
21496
22173
|
firstXref = cView.xref;
|
|
21497
|
-
|
|
22174
|
+
}
|
|
22175
|
+
unit.create.push(createTemplateOp(cView.xref, 'Case', Namespace.HTML, true, undefined /* TODO: figure out how i18n works with new control flow */, switchCase.sourceSpan));
|
|
21498
22176
|
const caseExpr = switchCase.expression ?
|
|
21499
22177
|
convertAst(switchCase.expression, unit.job, switchBlock.startSourceSpan) :
|
|
21500
22178
|
null;
|
|
21501
|
-
|
|
22179
|
+
const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr, cView.xref);
|
|
22180
|
+
conditions.push(conditionalCaseExpr);
|
|
21502
22181
|
ingestNodes(cView, switchCase.children);
|
|
21503
22182
|
}
|
|
21504
|
-
const conditional = createConditionalOp(firstXref, convertAst(switchBlock.expression, unit.job,
|
|
21505
|
-
conditional.conditions = conditions;
|
|
22183
|
+
const conditional = createConditionalOp(firstXref, convertAst(switchBlock.expression, unit.job, null), conditions, switchBlock.sourceSpan);
|
|
21506
22184
|
unit.update.push(conditional);
|
|
21507
22185
|
}
|
|
22186
|
+
function ingestDeferView(unit, suffix, children, sourceSpan) {
|
|
22187
|
+
if (children === undefined) {
|
|
22188
|
+
return null;
|
|
22189
|
+
}
|
|
22190
|
+
const secondaryView = unit.job.allocateView(unit.xref);
|
|
22191
|
+
ingestNodes(secondaryView, children);
|
|
22192
|
+
const templateOp = createTemplateOp(secondaryView.xref, `Defer${suffix}`, Namespace.HTML, true, undefined, sourceSpan);
|
|
22193
|
+
unit.create.push(templateOp);
|
|
22194
|
+
return templateOp;
|
|
22195
|
+
}
|
|
22196
|
+
function ingestDeferBlock(unit, deferBlock) {
|
|
22197
|
+
// Generate the defer main view and all secondary views.
|
|
22198
|
+
const main = ingestDeferView(unit, '', deferBlock.children, deferBlock.sourceSpan);
|
|
22199
|
+
const loading = ingestDeferView(unit, 'Loading', deferBlock.loading?.children, deferBlock.loading?.sourceSpan);
|
|
22200
|
+
const placeholder = ingestDeferView(unit, 'Placeholder', deferBlock.placeholder?.children, deferBlock.placeholder?.sourceSpan);
|
|
22201
|
+
const error = ingestDeferView(unit, 'Error', deferBlock.error?.children, deferBlock.error?.sourceSpan);
|
|
22202
|
+
// Create the main defer op, and ops for all secondary views.
|
|
22203
|
+
const deferOp = createDeferOp(unit.job.allocateXrefId(), main.xref, deferBlock.sourceSpan);
|
|
22204
|
+
unit.create.push(deferOp);
|
|
22205
|
+
if (loading && deferBlock.loading) {
|
|
22206
|
+
deferOp.loading =
|
|
22207
|
+
createDeferSecondaryOp(deferOp.xref, loading.xref, DeferSecondaryKind.Loading);
|
|
22208
|
+
if (deferBlock.loading.afterTime !== null || deferBlock.loading.minimumTime !== null) {
|
|
22209
|
+
deferOp.loading.constValue = [deferBlock.loading.minimumTime, deferBlock.loading.afterTime];
|
|
22210
|
+
}
|
|
22211
|
+
unit.create.push(deferOp.loading);
|
|
22212
|
+
}
|
|
22213
|
+
if (placeholder && deferBlock.placeholder) {
|
|
22214
|
+
deferOp.placeholder = createDeferSecondaryOp(deferOp.xref, placeholder.xref, DeferSecondaryKind.Placeholder);
|
|
22215
|
+
if (deferBlock.placeholder.minimumTime !== null) {
|
|
22216
|
+
deferOp.placeholder.constValue = [deferBlock.placeholder.minimumTime];
|
|
22217
|
+
}
|
|
22218
|
+
unit.create.push(deferOp.placeholder);
|
|
22219
|
+
}
|
|
22220
|
+
if (error && deferBlock.error) {
|
|
22221
|
+
deferOp.error =
|
|
22222
|
+
createDeferSecondaryOp(deferOp.xref, error.xref, DeferSecondaryKind.Error);
|
|
22223
|
+
unit.create.push(deferOp.error);
|
|
22224
|
+
}
|
|
22225
|
+
// Configure all defer conditions.
|
|
22226
|
+
const deferOnOp = createDeferOnOp(unit.job.allocateXrefId(), null);
|
|
22227
|
+
// Add all ops to the view.
|
|
22228
|
+
unit.create.push(deferOnOp);
|
|
22229
|
+
}
|
|
21508
22230
|
/**
|
|
21509
22231
|
* Convert a template AST expression into an output AST expression.
|
|
21510
22232
|
*/
|
|
@@ -21603,13 +22325,20 @@ function convertAst(ast, job, baseSourceSpan) {
|
|
|
21603
22325
|
* to their IR representation.
|
|
21604
22326
|
*/
|
|
21605
22327
|
function ingestBindings(unit, op, element) {
|
|
22328
|
+
let flags = BindingFlags.None;
|
|
22329
|
+
const isPlainTemplate = element instanceof Template && splitNsName(element.tagName ?? '')[1] === 'ng-template';
|
|
21606
22330
|
if (element instanceof Template) {
|
|
22331
|
+
flags |= BindingFlags.OnNgTemplateElement;
|
|
22332
|
+
if (isPlainTemplate) {
|
|
22333
|
+
flags |= BindingFlags.BindingTargetsTemplate;
|
|
22334
|
+
}
|
|
22335
|
+
const templateAttrFlags = flags | BindingFlags.BindingTargetsTemplate | BindingFlags.IsStructuralTemplateAttribute;
|
|
21607
22336
|
for (const attr of element.templateAttrs) {
|
|
21608
22337
|
if (attr instanceof TextAttribute) {
|
|
21609
|
-
ingestBinding(unit, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan,
|
|
22338
|
+
ingestBinding(unit, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, templateAttrFlags | BindingFlags.TextValue);
|
|
21610
22339
|
}
|
|
21611
22340
|
else {
|
|
21612
|
-
ingestBinding(unit, op.xref, attr.name, attr.value, attr.type, attr.unit, attr.securityContext, attr.sourceSpan,
|
|
22341
|
+
ingestBinding(unit, op.xref, attr.name, attr.value, attr.type, attr.unit, attr.securityContext, attr.sourceSpan, templateAttrFlags);
|
|
21613
22342
|
}
|
|
21614
22343
|
}
|
|
21615
22344
|
}
|
|
@@ -21617,10 +22346,10 @@ function ingestBindings(unit, op, element) {
|
|
|
21617
22346
|
// This is only attribute TextLiteral bindings, such as `attr.foo="bar"`. This can never be
|
|
21618
22347
|
// `[attr.foo]="bar"` or `attr.foo="{{bar}}"`, both of which will be handled as inputs with
|
|
21619
22348
|
// `BindingType.Attribute`.
|
|
21620
|
-
ingestBinding(unit, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan,
|
|
22349
|
+
ingestBinding(unit, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, flags | BindingFlags.TextValue);
|
|
21621
22350
|
}
|
|
21622
22351
|
for (const input of element.inputs) {
|
|
21623
|
-
ingestBinding(unit, op.xref, input.name, input.value, input.type, input.unit, input.securityContext, input.sourceSpan,
|
|
22352
|
+
ingestBinding(unit, op.xref, input.name, input.value, input.type, input.unit, input.securityContext, input.sourceSpan, flags);
|
|
21624
22353
|
}
|
|
21625
22354
|
for (const output of element.outputs) {
|
|
21626
22355
|
let listenerOp;
|
|
@@ -21629,6 +22358,10 @@ function ingestBindings(unit, op, element) {
|
|
|
21629
22358
|
throw Error('Animation listener should have a phase');
|
|
21630
22359
|
}
|
|
21631
22360
|
}
|
|
22361
|
+
if (element instanceof Template && !isPlainTemplate) {
|
|
22362
|
+
unit.create.push(createExtractedAttributeOp(op.xref, BindingKind.Property, output.name, null));
|
|
22363
|
+
continue;
|
|
22364
|
+
}
|
|
21632
22365
|
listenerOp =
|
|
21633
22366
|
createListenerOp(op.xref, output.name, op.tag, output.phase, false, output.sourceSpan);
|
|
21634
22367
|
// if output.handler is a chain, then push each statement from the chain separately, and
|
|
@@ -21664,10 +22397,37 @@ const BINDING_KINDS = new Map([
|
|
|
21664
22397
|
[3 /* e.BindingType.Style */, BindingKind.StyleProperty],
|
|
21665
22398
|
[4 /* e.BindingType.Animation */, BindingKind.Animation],
|
|
21666
22399
|
]);
|
|
21667
|
-
|
|
22400
|
+
var BindingFlags;
|
|
22401
|
+
(function (BindingFlags) {
|
|
22402
|
+
BindingFlags[BindingFlags["None"] = 0] = "None";
|
|
22403
|
+
/**
|
|
22404
|
+
* The binding is to a static text literal and not to an expression.
|
|
22405
|
+
*/
|
|
22406
|
+
BindingFlags[BindingFlags["TextValue"] = 1] = "TextValue";
|
|
22407
|
+
/**
|
|
22408
|
+
* The binding belongs to the `<ng-template>` side of a `t.Template`.
|
|
22409
|
+
*/
|
|
22410
|
+
BindingFlags[BindingFlags["BindingTargetsTemplate"] = 2] = "BindingTargetsTemplate";
|
|
22411
|
+
/**
|
|
22412
|
+
* The binding is on a structural directive.
|
|
22413
|
+
*/
|
|
22414
|
+
BindingFlags[BindingFlags["IsStructuralTemplateAttribute"] = 4] = "IsStructuralTemplateAttribute";
|
|
22415
|
+
/**
|
|
22416
|
+
* The binding is on a `t.Template`.
|
|
22417
|
+
*/
|
|
22418
|
+
BindingFlags[BindingFlags["OnNgTemplateElement"] = 8] = "OnNgTemplateElement";
|
|
22419
|
+
})(BindingFlags || (BindingFlags = {}));
|
|
22420
|
+
function ingestBinding(view, xref, name, value, type, unit, securityContext, sourceSpan, flags) {
|
|
21668
22421
|
if (value instanceof ASTWithSource) {
|
|
21669
22422
|
value = value.ast;
|
|
21670
22423
|
}
|
|
22424
|
+
if (flags & BindingFlags.OnNgTemplateElement && !(flags & BindingFlags.BindingTargetsTemplate) &&
|
|
22425
|
+
type === 0 /* e.BindingType.Property */) {
|
|
22426
|
+
// This binding only exists for later const extraction, and is not an actual binding to be
|
|
22427
|
+
// created.
|
|
22428
|
+
view.create.push(createExtractedAttributeOp(xref, BindingKind.Property, name, null));
|
|
22429
|
+
return;
|
|
22430
|
+
}
|
|
21671
22431
|
let expression;
|
|
21672
22432
|
// TODO: We could easily generate source maps for subexpressions in these cases, but
|
|
21673
22433
|
// TemplateDefinitionBuilder does not. Should we do so?
|
|
@@ -21681,7 +22441,7 @@ function ingestBinding(view, xref, name, value, type, unit, securityContext, sou
|
|
|
21681
22441
|
expression = value;
|
|
21682
22442
|
}
|
|
21683
22443
|
const kind = BINDING_KINDS.get(type);
|
|
21684
|
-
view.update.push(createBindingOp(xref, kind, name, expression, unit, securityContext,
|
|
22444
|
+
view.update.push(createBindingOp(xref, kind, name, expression, unit, securityContext, !!(flags & BindingFlags.TextValue), !!(flags & BindingFlags.IsStructuralTemplateAttribute), sourceSpan));
|
|
21685
22445
|
}
|
|
21686
22446
|
/**
|
|
21687
22447
|
* Process all of the local references on an element-like structure in the template AST and
|
|
@@ -22862,13 +23622,13 @@ function normalizeNgContentSelect(selectAttr) {
|
|
|
22862
23622
|
/** Pattern for the expression in a for loop block. */
|
|
22863
23623
|
const FOR_LOOP_EXPRESSION_PATTERN = /^\s*([0-9A-Za-z_$]*)\s+of\s+(.*)/;
|
|
22864
23624
|
/** Pattern for the tracking expression in a for loop block. */
|
|
22865
|
-
const FOR_LOOP_TRACK_PATTERN = /^track\s+(
|
|
23625
|
+
const FOR_LOOP_TRACK_PATTERN = /^track\s+([\S\s]*)/;
|
|
22866
23626
|
/** Pattern for the `as` expression in a conditional block. */
|
|
22867
23627
|
const CONDITIONAL_ALIAS_PATTERN = /^as\s+(.*)/;
|
|
22868
23628
|
/** Pattern used to identify an `else if` block. */
|
|
22869
23629
|
const ELSE_IF_PATTERN = /^else[^\S\r\n]+if/;
|
|
22870
23630
|
/** Pattern used to identify a `let` parameter. */
|
|
22871
|
-
const FOR_LOOP_LET_PATTERN = /^let\s+(
|
|
23631
|
+
const FOR_LOOP_LET_PATTERN = /^let\s+([\S\s]*)/;
|
|
22872
23632
|
/** Names of variables that are allowed to be used in the `let` expression of a `for` loop. */
|
|
22873
23633
|
const ALLOWED_FOR_LOOP_LET_VARIABLES = new Set(['$index', '$first', '$last', '$even', '$odd', '$count']);
|
|
22874
23634
|
/**
|
|
@@ -22889,28 +23649,33 @@ function isConnectedIfLoopBlock(name) {
|
|
|
22889
23649
|
function createIfBlock(ast, connectedBlocks, visitor, bindingParser) {
|
|
22890
23650
|
const errors = validateIfConnectedBlocks(connectedBlocks);
|
|
22891
23651
|
const branches = [];
|
|
22892
|
-
if (errors.length > 0) {
|
|
22893
|
-
return { node: null, errors };
|
|
22894
|
-
}
|
|
22895
23652
|
const mainBlockParams = parseConditionalBlockParameters(ast, errors, bindingParser);
|
|
22896
23653
|
if (mainBlockParams !== null) {
|
|
22897
|
-
branches.push(new IfBlockBranch(mainBlockParams.expression, visitAll(visitor, ast.children, ast.children), mainBlockParams.expressionAlias, ast.sourceSpan, ast.startSourceSpan));
|
|
23654
|
+
branches.push(new IfBlockBranch(mainBlockParams.expression, visitAll(visitor, ast.children, ast.children), mainBlockParams.expressionAlias, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan));
|
|
22898
23655
|
}
|
|
22899
|
-
// Assumes that the structure is valid since we validated it above.
|
|
22900
23656
|
for (const block of connectedBlocks) {
|
|
22901
|
-
const children = visitAll(visitor, block.children, block.children);
|
|
22902
23657
|
if (ELSE_IF_PATTERN.test(block.name)) {
|
|
22903
23658
|
const params = parseConditionalBlockParameters(block, errors, bindingParser);
|
|
22904
23659
|
if (params !== null) {
|
|
22905
|
-
|
|
23660
|
+
const children = visitAll(visitor, block.children, block.children);
|
|
23661
|
+
branches.push(new IfBlockBranch(params.expression, children, params.expressionAlias, block.sourceSpan, block.startSourceSpan, block.endSourceSpan));
|
|
22906
23662
|
}
|
|
22907
23663
|
}
|
|
22908
23664
|
else if (block.name === 'else') {
|
|
22909
|
-
|
|
23665
|
+
const children = visitAll(visitor, block.children, block.children);
|
|
23666
|
+
branches.push(new IfBlockBranch(null, children, null, block.sourceSpan, block.startSourceSpan, block.endSourceSpan));
|
|
22910
23667
|
}
|
|
22911
23668
|
}
|
|
23669
|
+
// The outer IfBlock should have a span that encapsulates all branches.
|
|
23670
|
+
const ifBlockStartSourceSpan = branches.length > 0 ? branches[0].startSourceSpan : ast.startSourceSpan;
|
|
23671
|
+
const ifBlockEndSourceSpan = branches.length > 0 ? branches[branches.length - 1].endSourceSpan : ast.endSourceSpan;
|
|
23672
|
+
let wholeSourceSpan = ast.sourceSpan;
|
|
23673
|
+
const lastBranch = branches[branches.length - 1];
|
|
23674
|
+
if (lastBranch !== undefined) {
|
|
23675
|
+
wholeSourceSpan = new ParseSourceSpan(ifBlockStartSourceSpan.start, lastBranch.sourceSpan.end);
|
|
23676
|
+
}
|
|
22912
23677
|
return {
|
|
22913
|
-
node: new IfBlock(branches,
|
|
23678
|
+
node: new IfBlock(branches, wholeSourceSpan, ast.startSourceSpan, ifBlockEndSourceSpan),
|
|
22914
23679
|
errors,
|
|
22915
23680
|
};
|
|
22916
23681
|
}
|
|
@@ -22929,7 +23694,7 @@ function createForLoop(ast, connectedBlocks, visitor, bindingParser) {
|
|
|
22929
23694
|
errors.push(new ParseError(block.sourceSpan, '@empty block cannot have parameters'));
|
|
22930
23695
|
}
|
|
22931
23696
|
else {
|
|
22932
|
-
empty = new ForLoopBlockEmpty(visitAll(visitor, block.children, block.children), block.sourceSpan, block.startSourceSpan);
|
|
23697
|
+
empty = new ForLoopBlockEmpty(visitAll(visitor, block.children, block.children), block.sourceSpan, block.startSourceSpan, block.endSourceSpan);
|
|
22933
23698
|
}
|
|
22934
23699
|
}
|
|
22935
23700
|
else {
|
|
@@ -22938,10 +23703,16 @@ function createForLoop(ast, connectedBlocks, visitor, bindingParser) {
|
|
|
22938
23703
|
}
|
|
22939
23704
|
if (params !== null) {
|
|
22940
23705
|
if (params.trackBy === null) {
|
|
23706
|
+
// TODO: We should not fail here, and instead try to produce some AST for the language
|
|
23707
|
+
// service.
|
|
22941
23708
|
errors.push(new ParseError(ast.sourceSpan, '@for loop must have a "track" expression'));
|
|
22942
23709
|
}
|
|
22943
23710
|
else {
|
|
22944
|
-
|
|
23711
|
+
// The `for` block has a main span that includes the `empty` branch. For only the span of the
|
|
23712
|
+
// main `for` body, use `mainSourceSpan`.
|
|
23713
|
+
const endSpan = empty?.endSourceSpan ?? ast.endSourceSpan;
|
|
23714
|
+
const sourceSpan = new ParseSourceSpan(ast.sourceSpan.start, endSpan?.end ?? ast.sourceSpan.end);
|
|
23715
|
+
node = new ForLoopBlock(params.itemName, params.expression, params.trackBy, params.context, visitAll(visitor, ast.children, ast.children), empty, sourceSpan, ast.sourceSpan, ast.startSourceSpan, endSpan);
|
|
22945
23716
|
}
|
|
22946
23717
|
}
|
|
22947
23718
|
return { node, errors };
|
|
@@ -22949,21 +23720,25 @@ function createForLoop(ast, connectedBlocks, visitor, bindingParser) {
|
|
|
22949
23720
|
/** Creates a switch block from an HTML AST node. */
|
|
22950
23721
|
function createSwitchBlock(ast, visitor, bindingParser) {
|
|
22951
23722
|
const errors = validateSwitchBlock(ast);
|
|
22952
|
-
|
|
22953
|
-
|
|
22954
|
-
|
|
22955
|
-
const primaryExpression = parseBlockParameterToBinding(ast.parameters[0], bindingParser);
|
|
23723
|
+
const primaryExpression = ast.parameters.length > 0 ?
|
|
23724
|
+
parseBlockParameterToBinding(ast.parameters[0], bindingParser) :
|
|
23725
|
+
bindingParser.parseBinding('', false, ast.sourceSpan, 0);
|
|
22956
23726
|
const cases = [];
|
|
23727
|
+
const unknownBlocks = [];
|
|
22957
23728
|
let defaultCase = null;
|
|
22958
23729
|
// Here we assume that all the blocks are valid given that we validated them above.
|
|
22959
23730
|
for (const node of ast.children) {
|
|
22960
23731
|
if (!(node instanceof Block)) {
|
|
22961
23732
|
continue;
|
|
22962
23733
|
}
|
|
23734
|
+
if ((node.name !== 'case' || node.parameters.length === 0) && node.name !== 'default') {
|
|
23735
|
+
unknownBlocks.push(new UnknownBlock(node.name, node.sourceSpan));
|
|
23736
|
+
continue;
|
|
23737
|
+
}
|
|
22963
23738
|
const expression = node.name === 'case' ?
|
|
22964
23739
|
parseBlockParameterToBinding(node.parameters[0], bindingParser) :
|
|
22965
23740
|
null;
|
|
22966
|
-
const ast = new SwitchBlockCase(expression, visitAll(visitor, node.children, node.children), node.sourceSpan, node.startSourceSpan);
|
|
23741
|
+
const ast = new SwitchBlockCase(expression, visitAll(visitor, node.children, node.children), node.sourceSpan, node.startSourceSpan, node.endSourceSpan);
|
|
22967
23742
|
if (expression === null) {
|
|
22968
23743
|
defaultCase = ast;
|
|
22969
23744
|
}
|
|
@@ -22976,7 +23751,7 @@ function createSwitchBlock(ast, visitor, bindingParser) {
|
|
|
22976
23751
|
cases.push(defaultCase);
|
|
22977
23752
|
}
|
|
22978
23753
|
return {
|
|
22979
|
-
node: new SwitchBlock(primaryExpression, cases, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan),
|
|
23754
|
+
node: new SwitchBlock(primaryExpression, cases, unknownBlocks, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan),
|
|
22980
23755
|
errors
|
|
22981
23756
|
};
|
|
22982
23757
|
}
|
|
@@ -23020,8 +23795,10 @@ function parseForLoopParameters(block, errors, bindingParser) {
|
|
|
23020
23795
|
// Fill out any variables that haven't been defined explicitly.
|
|
23021
23796
|
for (const variableName of ALLOWED_FOR_LOOP_LET_VARIABLES) {
|
|
23022
23797
|
if (!result.context.hasOwnProperty(variableName)) {
|
|
23023
|
-
|
|
23024
|
-
|
|
23798
|
+
// Give ambiently-available context variables empty spans at the end of the start of the `for`
|
|
23799
|
+
// block, since they are not explicitly defined.
|
|
23800
|
+
const emptySpanAfterForBlockStart = new ParseSourceSpan(block.startSourceSpan.end, block.startSourceSpan.end);
|
|
23801
|
+
result.context[variableName] = new Variable(variableName, variableName, emptySpanAfterForBlockStart, emptySpanAfterForBlockStart);
|
|
23025
23802
|
}
|
|
23026
23803
|
}
|
|
23027
23804
|
return result;
|
|
@@ -23516,7 +24293,17 @@ function createDeferredBlock(ast, connectedBlocks, visitor, bindingParser) {
|
|
|
23516
24293
|
const errors = [];
|
|
23517
24294
|
const { placeholder, loading, error } = parseConnectedBlocks(connectedBlocks, errors, visitor);
|
|
23518
24295
|
const { triggers, prefetchTriggers } = parsePrimaryTriggers(ast.parameters, bindingParser, errors, placeholder);
|
|
23519
|
-
|
|
24296
|
+
// The `defer` block has a main span encompassing all of the connected branches as well. For the
|
|
24297
|
+
// span of only the first "main" branch, use `mainSourceSpan`.
|
|
24298
|
+
let lastEndSourceSpan = ast.endSourceSpan;
|
|
24299
|
+
let endOfLastSourceSpan = ast.sourceSpan.end;
|
|
24300
|
+
if (connectedBlocks.length > 0) {
|
|
24301
|
+
const lastConnectedBlock = connectedBlocks[connectedBlocks.length - 1];
|
|
24302
|
+
lastEndSourceSpan = lastConnectedBlock.endSourceSpan;
|
|
24303
|
+
endOfLastSourceSpan = lastConnectedBlock.sourceSpan.end;
|
|
24304
|
+
}
|
|
24305
|
+
const mainDeferredSourceSpan = new ParseSourceSpan(ast.sourceSpan.start, endOfLastSourceSpan);
|
|
24306
|
+
const node = new DeferredBlock(visitAll(visitor, ast.children, ast.children), triggers, prefetchTriggers, placeholder, loading, error, mainDeferredSourceSpan, ast.sourceSpan, ast.startSourceSpan, lastEndSourceSpan);
|
|
23520
24307
|
return { node, errors };
|
|
23521
24308
|
}
|
|
23522
24309
|
function parseConnectedBlocks(connectedBlocks, errors, visitor) {
|
|
@@ -23891,26 +24678,6 @@ class HtmlAstToIvyAst {
|
|
|
23891
24678
|
if (this.processedNodes.has(block)) {
|
|
23892
24679
|
return null;
|
|
23893
24680
|
}
|
|
23894
|
-
if (!this.options.enabledBlockTypes.has(block.name)) {
|
|
23895
|
-
let errorMessage;
|
|
23896
|
-
if (isConnectedDeferLoopBlock(block.name)) {
|
|
23897
|
-
errorMessage = `@${block.name} block can only be used after an @defer block.`;
|
|
23898
|
-
this.processedNodes.add(block);
|
|
23899
|
-
}
|
|
23900
|
-
else if (isConnectedForLoopBlock(block.name)) {
|
|
23901
|
-
errorMessage = `@${block.name} block can only be used after an @for block.`;
|
|
23902
|
-
this.processedNodes.add(block);
|
|
23903
|
-
}
|
|
23904
|
-
else if (isConnectedIfLoopBlock(block.name)) {
|
|
23905
|
-
errorMessage = `@${block.name} block can only be used after an @if or @else if block.`;
|
|
23906
|
-
this.processedNodes.add(block);
|
|
23907
|
-
}
|
|
23908
|
-
else {
|
|
23909
|
-
errorMessage = `Unrecognized block @${block.name}.`;
|
|
23910
|
-
}
|
|
23911
|
-
this.reportError(errorMessage, block.sourceSpan);
|
|
23912
|
-
return null;
|
|
23913
|
-
}
|
|
23914
24681
|
let result = null;
|
|
23915
24682
|
switch (block.name) {
|
|
23916
24683
|
case 'defer':
|
|
@@ -23926,9 +24693,25 @@ class HtmlAstToIvyAst {
|
|
|
23926
24693
|
result = createIfBlock(block, this.findConnectedBlocks(index, context, isConnectedIfLoopBlock), this, this.bindingParser);
|
|
23927
24694
|
break;
|
|
23928
24695
|
default:
|
|
24696
|
+
let errorMessage;
|
|
24697
|
+
if (isConnectedDeferLoopBlock(block.name)) {
|
|
24698
|
+
errorMessage = `@${block.name} block can only be used after an @defer block.`;
|
|
24699
|
+
this.processedNodes.add(block);
|
|
24700
|
+
}
|
|
24701
|
+
else if (isConnectedForLoopBlock(block.name)) {
|
|
24702
|
+
errorMessage = `@${block.name} block can only be used after an @for block.`;
|
|
24703
|
+
this.processedNodes.add(block);
|
|
24704
|
+
}
|
|
24705
|
+
else if (isConnectedIfLoopBlock(block.name)) {
|
|
24706
|
+
errorMessage = `@${block.name} block can only be used after an @if or @else if block.`;
|
|
24707
|
+
this.processedNodes.add(block);
|
|
24708
|
+
}
|
|
24709
|
+
else {
|
|
24710
|
+
errorMessage = `Unrecognized block @${block.name}.`;
|
|
24711
|
+
}
|
|
23929
24712
|
result = {
|
|
23930
|
-
node:
|
|
23931
|
-
errors: [new ParseError(block.sourceSpan,
|
|
24713
|
+
node: new UnknownBlock(block.name, block.sourceSpan),
|
|
24714
|
+
errors: [new ParseError(block.sourceSpan, errorMessage)],
|
|
23932
24715
|
};
|
|
23933
24716
|
break;
|
|
23934
24717
|
}
|
|
@@ -24517,6 +25300,7 @@ class TemplateDefinitionBuilder {
|
|
|
24517
25300
|
this.visitIfBlockBranch = invalid;
|
|
24518
25301
|
this.visitSwitchBlockCase = invalid;
|
|
24519
25302
|
this.visitForLoopBlockEmpty = invalid;
|
|
25303
|
+
this.visitUnknownBlock = invalid;
|
|
24520
25304
|
this._bindingScope = parentBindingScope.nestedScope(level);
|
|
24521
25305
|
// Turn the relative context file path into an identifier by replacing non-alphanumeric
|
|
24522
25306
|
// characters with underscores.
|
|
@@ -25242,18 +26026,17 @@ class TemplateDefinitionBuilder {
|
|
|
25242
26026
|
// callback in order to generate the correct expressions when pipes or pure functions are
|
|
25243
26027
|
// used inside the branch expressions.
|
|
25244
26028
|
const branchData = block.branches.map(({ expression, expressionAlias, children, sourceSpan }) => {
|
|
25245
|
-
const processedExpression = expression === null ? null : expression.visit(this._valueConverter);
|
|
25246
26029
|
// If the branch has an alias, it'll be assigned directly to the container's context.
|
|
25247
26030
|
// We define a variable referring directly to the context so that any nested usages can be
|
|
25248
26031
|
// rewritten to refer to it.
|
|
25249
26032
|
const variables = expressionAlias !== null ?
|
|
25250
26033
|
[new Variable(expressionAlias.name, DIRECT_CONTEXT_REFERENCE, expressionAlias.sourceSpan, expressionAlias.keySpan)] :
|
|
25251
26034
|
undefined;
|
|
25252
|
-
|
|
25253
|
-
|
|
25254
|
-
|
|
25255
|
-
|
|
25256
|
-
};
|
|
26035
|
+
// Note: the template needs to be created *before* we process the expression,
|
|
26036
|
+
// otherwise pipes injecting some symbols won't work (see #52102).
|
|
26037
|
+
const index = this.createEmbeddedTemplateFn(null, children, '_Conditional', sourceSpan, variables);
|
|
26038
|
+
const processedExpression = expression === null ? null : expression.visit(this._valueConverter);
|
|
26039
|
+
return { index, expression: processedExpression, alias: expressionAlias };
|
|
25257
26040
|
});
|
|
25258
26041
|
// Use the index of the first block as the index for the entire container.
|
|
25259
26042
|
const containerIndex = branchData[0].index;
|
|
@@ -25299,20 +26082,21 @@ class TemplateDefinitionBuilder {
|
|
|
25299
26082
|
this.updateInstructionWithAdvance(containerIndex, block.branches[0].sourceSpan, Identifiers.conditional, paramsCallback);
|
|
25300
26083
|
}
|
|
25301
26084
|
visitSwitchBlock(block) {
|
|
25302
|
-
const blockExpression = block.expression.visit(this._valueConverter);
|
|
25303
|
-
this.allocateBindingSlots(null); // Allocate a slot for the primary block expression.
|
|
25304
26085
|
// We have to process the block in two steps: once here and again in the update instruction
|
|
25305
26086
|
// callback in order to generate the correct expressions when pipes or pure functions are used.
|
|
25306
26087
|
const caseData = block.cases.map(currentCase => {
|
|
25307
|
-
|
|
25308
|
-
|
|
25309
|
-
|
|
25310
|
-
|
|
25311
|
-
|
|
25312
|
-
};
|
|
26088
|
+
const index = this.createEmbeddedTemplateFn(null, currentCase.children, '_Case', currentCase.sourceSpan);
|
|
26089
|
+
const expression = currentCase.expression === null ?
|
|
26090
|
+
null :
|
|
26091
|
+
currentCase.expression.visit(this._valueConverter);
|
|
26092
|
+
return { index, expression };
|
|
25313
26093
|
});
|
|
25314
26094
|
// Use the index of the first block as the index for the entire container.
|
|
25315
26095
|
const containerIndex = caseData[0].index;
|
|
26096
|
+
// Note: the expression needs to be processed *after* the template,
|
|
26097
|
+
// otherwise pipes injecting some symbols won't work (see #52102).
|
|
26098
|
+
const blockExpression = block.expression.visit(this._valueConverter);
|
|
26099
|
+
this.allocateBindingSlots(null); // Allocate a slot for the primary block expression.
|
|
25316
26100
|
this.updateInstructionWithAdvance(containerIndex, block.sourceSpan, Identifiers.conditional, () => {
|
|
25317
26101
|
const generateCases = (caseIndex) => {
|
|
25318
26102
|
// If we've gone beyond the last branch, return the special -1
|
|
@@ -25380,12 +26164,17 @@ class TemplateDefinitionBuilder {
|
|
|
25380
26164
|
literal(errorIndex),
|
|
25381
26165
|
loadingConsts?.length ? this.addToConsts(literalArr(loadingConsts)) : TYPED_NULL_EXPR,
|
|
25382
26166
|
placeholderConsts ? this.addToConsts(placeholderConsts) : TYPED_NULL_EXPR,
|
|
26167
|
+
(loadingConsts?.length || placeholderConsts) ?
|
|
26168
|
+
importExpr(Identifiers.deferEnableTimerScheduling) :
|
|
26169
|
+
TYPED_NULL_EXPR,
|
|
25383
26170
|
]));
|
|
25384
|
-
this.createDeferTriggerInstructions(deferredIndex, triggers, metadata, false);
|
|
25385
|
-
this.createDeferTriggerInstructions(deferredIndex, prefetchTriggers, metadata, true);
|
|
25386
26171
|
// Allocate an extra data slot right after a defer block slot to store
|
|
25387
26172
|
// instance-specific state of that defer block at runtime.
|
|
25388
26173
|
this.allocateDataSlot();
|
|
26174
|
+
// Note: the triggers need to be processed *after* the various templates,
|
|
26175
|
+
// otherwise pipes injecting some symbols won't work (see #52102).
|
|
26176
|
+
this.createDeferTriggerInstructions(deferredIndex, triggers, metadata, false);
|
|
26177
|
+
this.createDeferTriggerInstructions(deferredIndex, prefetchTriggers, metadata, true);
|
|
25389
26178
|
}
|
|
25390
26179
|
createDeferredDepsFunction(name, metadata) {
|
|
25391
26180
|
if (metadata.deps.length === 0) {
|
|
@@ -25477,12 +26266,13 @@ class TemplateDefinitionBuilder {
|
|
|
25477
26266
|
// are implicitly inferred by the runtime to index + 1 and index + 2.
|
|
25478
26267
|
const blockIndex = this.allocateDataSlot();
|
|
25479
26268
|
const primaryData = this.prepareEmbeddedTemplateFn(block.children, '_For', [block.item, block.contextVariables.$index, block.contextVariables.$count]);
|
|
25480
|
-
const emptyData = block.empty === null ?
|
|
25481
|
-
null :
|
|
25482
|
-
this.prepareEmbeddedTemplateFn(block.empty.children, '_ForEmpty');
|
|
25483
26269
|
const { expression: trackByExpression, usesComponentInstance: trackByUsesComponentInstance } = this.createTrackByFunction(block);
|
|
25484
|
-
|
|
25485
|
-
|
|
26270
|
+
let emptyData = null;
|
|
26271
|
+
if (block.empty !== null) {
|
|
26272
|
+
emptyData = this.prepareEmbeddedTemplateFn(block.empty.children, '_ForEmpty');
|
|
26273
|
+
// Allocate an extra slot for the empty block tracking.
|
|
26274
|
+
this.allocateBindingSlots(null);
|
|
26275
|
+
}
|
|
25486
26276
|
this.registerComputedLoopVariables(block, primaryData.scope);
|
|
25487
26277
|
// `repeaterCreate(0, ...)`
|
|
25488
26278
|
this.creationInstruction(block.sourceSpan, Identifiers.repeaterCreate, () => {
|
|
@@ -25502,6 +26292,11 @@ class TemplateDefinitionBuilder {
|
|
|
25502
26292
|
}
|
|
25503
26293
|
return params;
|
|
25504
26294
|
});
|
|
26295
|
+
// Note: the expression needs to be processed *after* the template,
|
|
26296
|
+
// otherwise pipes injecting some symbols won't work (see #52102).
|
|
26297
|
+
// Note: we don't allocate binding slots for this expression,
|
|
26298
|
+
// because its value isn't stored in the LView.
|
|
26299
|
+
const value = block.expression.visit(this._valueConverter);
|
|
25505
26300
|
// `repeater(0, iterable)`
|
|
25506
26301
|
this.updateInstruction(block.sourceSpan, Identifiers.repeater, () => [literal(blockIndex), this.convertPropertyBinding(value)]);
|
|
25507
26302
|
}
|
|
@@ -26377,7 +27172,7 @@ function parseTemplate(template, templateUrl, options = {}) {
|
|
|
26377
27172
|
leadingTriviaChars: LEADING_TRIVIA_CHARS,
|
|
26378
27173
|
...options,
|
|
26379
27174
|
tokenizeExpansionForms: true,
|
|
26380
|
-
tokenizeBlocks: options.
|
|
27175
|
+
tokenizeBlocks: options.enableBlockSyntax ?? true,
|
|
26381
27176
|
});
|
|
26382
27177
|
if (!options.alwaysAttemptHtmlToR3AstConversion && parseResult.errors &&
|
|
26383
27178
|
parseResult.errors.length > 0) {
|
|
@@ -26429,10 +27224,7 @@ function parseTemplate(template, templateUrl, options = {}) {
|
|
|
26429
27224
|
rootNodes = visitAll(new I18nMetaVisitor(interpolationConfig, /* keepI18nAttrs */ false), rootNodes);
|
|
26430
27225
|
}
|
|
26431
27226
|
}
|
|
26432
|
-
const { nodes, errors, styleUrls, styles, ngContentSelectors, commentNodes } = htmlAstToRender3Ast(rootNodes, bindingParser, {
|
|
26433
|
-
collectCommentNodes: !!options.collectCommentNodes,
|
|
26434
|
-
enabledBlockTypes: options.enabledBlockTypes || new Set(),
|
|
26435
|
-
});
|
|
27227
|
+
const { nodes, errors, styleUrls, styles, ngContentSelectors, commentNodes } = htmlAstToRender3Ast(rootNodes, bindingParser, { collectCommentNodes: !!options.collectCommentNodes });
|
|
26436
27228
|
errors.push(...parseResult.errors, ...i18nMetaResult.errors);
|
|
26437
27229
|
const parsedTemplate = {
|
|
26438
27230
|
interpolationConfig,
|
|
@@ -26707,14 +27499,14 @@ function compileComponentFromMetadata(meta, constantPool, bindingParser) {
|
|
|
26707
27499
|
// - either as an array:
|
|
26708
27500
|
// `consts: [['one', 'two'], ['three', 'four']]`
|
|
26709
27501
|
// - or as a factory function in case additional statements are present (to support i18n):
|
|
26710
|
-
// `consts:
|
|
27502
|
+
// `consts: () => { var i18n_0; if (ngI18nClosureMode) {...} else {...} return [i18n_0];
|
|
26711
27503
|
// }`
|
|
26712
27504
|
const { constExpressions, prepareStatements } = templateBuilder.getConsts();
|
|
26713
27505
|
if (constExpressions.length > 0) {
|
|
26714
27506
|
let constsExpr = literalArr(constExpressions);
|
|
26715
27507
|
// Prepare statements are present - turn `consts` into a function.
|
|
26716
27508
|
if (prepareStatements.length > 0) {
|
|
26717
|
-
constsExpr =
|
|
27509
|
+
constsExpr = arrowFn([], [...prepareStatements, new ReturnStatement(constsExpr)]);
|
|
26718
27510
|
}
|
|
26719
27511
|
definitionMap.set('consts', constsExpr);
|
|
26720
27512
|
}
|
|
@@ -26735,7 +27527,9 @@ function compileComponentFromMetadata(meta, constantPool, bindingParser) {
|
|
|
26735
27527
|
definitionMap.set('vars', literal(tpl.root.vars));
|
|
26736
27528
|
if (tpl.consts.length > 0) {
|
|
26737
27529
|
if (tpl.constsInitializers.length > 0) {
|
|
26738
|
-
definitionMap.set('consts',
|
|
27530
|
+
definitionMap.set('consts', arrowFn([], [
|
|
27531
|
+
...tpl.constsInitializers, new ReturnStatement(literalArr(tpl.consts))
|
|
27532
|
+
]));
|
|
26739
27533
|
}
|
|
26740
27534
|
else {
|
|
26741
27535
|
definitionMap.set('consts', literalArr(tpl.consts));
|
|
@@ -26829,11 +27623,11 @@ function compileDeclarationList(list, mode) {
|
|
|
26829
27623
|
return list;
|
|
26830
27624
|
case 1 /* DeclarationListEmitMode.Closure */:
|
|
26831
27625
|
// directives: function () { return [MyDir]; }
|
|
26832
|
-
return
|
|
27626
|
+
return arrowFn([], list);
|
|
26833
27627
|
case 2 /* DeclarationListEmitMode.ClosureResolved */:
|
|
26834
27628
|
// directives: function () { return [MyDir].map(ng.resolveForwardRef); }
|
|
26835
27629
|
const resolvedList = list.prop('map').callFn([importExpr(Identifiers.resolveForwardRef)]);
|
|
26836
|
-
return
|
|
27630
|
+
return arrowFn([], resolvedList);
|
|
26837
27631
|
case 3 /* DeclarationListEmitMode.RuntimeResolved */:
|
|
26838
27632
|
throw new Error(`Unsupported with an array of pre-resolved dependencies`);
|
|
26839
27633
|
}
|
|
@@ -27523,6 +28317,7 @@ class Scope {
|
|
|
27523
28317
|
visitTextAttribute(attr) { }
|
|
27524
28318
|
visitIcu(icu) { }
|
|
27525
28319
|
visitDeferredTrigger(trigger) { }
|
|
28320
|
+
visitUnknownBlock(block) { }
|
|
27526
28321
|
maybeDeclare(thing) {
|
|
27527
28322
|
// Declare something with a name, as long as that name isn't taken.
|
|
27528
28323
|
if (!this.namedEntities.has(thing.name)) {
|
|
@@ -27724,6 +28519,7 @@ class DirectiveBinder {
|
|
|
27724
28519
|
visitBoundText(text) { }
|
|
27725
28520
|
visitIcu(icu) { }
|
|
27726
28521
|
visitDeferredTrigger(trigger) { }
|
|
28522
|
+
visitUnknownBlock(block) { }
|
|
27727
28523
|
}
|
|
27728
28524
|
/**
|
|
27729
28525
|
* Processes a template and extract metadata about expressions and symbols within.
|
|
@@ -27852,6 +28648,8 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
27852
28648
|
visitText(text) { }
|
|
27853
28649
|
visitContent(content) { }
|
|
27854
28650
|
visitTextAttribute(attribute) { }
|
|
28651
|
+
visitUnknownBlock(block) { }
|
|
28652
|
+
visitDeferredTrigger() { }
|
|
27855
28653
|
visitIcu(icu) {
|
|
27856
28654
|
Object.keys(icu.vars).forEach(key => icu.vars[key].visit(this));
|
|
27857
28655
|
Object.keys(icu.placeholders).forEach(key => icu.placeholders[key].visit(this));
|
|
@@ -27866,15 +28664,12 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
27866
28664
|
visitDeferredBlock(deferred) {
|
|
27867
28665
|
this.deferBlocks.add(deferred);
|
|
27868
28666
|
this.ingestScopedNode(deferred);
|
|
28667
|
+
deferred.triggers.when?.value.visit(this);
|
|
28668
|
+
deferred.prefetchTriggers.when?.value.visit(this);
|
|
27869
28669
|
deferred.placeholder && this.visitNode(deferred.placeholder);
|
|
27870
28670
|
deferred.loading && this.visitNode(deferred.loading);
|
|
27871
28671
|
deferred.error && this.visitNode(deferred.error);
|
|
27872
28672
|
}
|
|
27873
|
-
visitDeferredTrigger(trigger) {
|
|
27874
|
-
if (trigger instanceof BoundDeferredTrigger) {
|
|
27875
|
-
trigger.value.visit(this);
|
|
27876
|
-
}
|
|
27877
|
-
}
|
|
27878
28673
|
visitDeferredBlockPlaceholder(block) {
|
|
27879
28674
|
this.ingestScopedNode(block);
|
|
27880
28675
|
}
|
|
@@ -28113,11 +28908,6 @@ function extractScopedNodeEntities(rootScope) {
|
|
|
28113
28908
|
class ResourceLoader {
|
|
28114
28909
|
}
|
|
28115
28910
|
|
|
28116
|
-
let enabledBlockTypes;
|
|
28117
|
-
/** Temporary utility that enables specific block types in JIT compilations. */
|
|
28118
|
-
function ɵsetEnabledBlockTypes(types) {
|
|
28119
|
-
enabledBlockTypes = types.length > 0 ? new Set(types) : undefined;
|
|
28120
|
-
}
|
|
28121
28911
|
class CompilerFacadeImpl {
|
|
28122
28912
|
constructor(jitEvaluator = new JitEvaluator()) {
|
|
28123
28913
|
this.jitEvaluator = jitEvaluator;
|
|
@@ -28523,7 +29313,7 @@ function convertPipeDeclarationToMetadata(pipe) {
|
|
|
28523
29313
|
function parseJitTemplate(template, typeName, sourceMapUrl, preserveWhitespaces, interpolation) {
|
|
28524
29314
|
const interpolationConfig = interpolation ? InterpolationConfig.fromArray(interpolation) : DEFAULT_INTERPOLATION_CONFIG;
|
|
28525
29315
|
// Parse the template and check for errors.
|
|
28526
|
-
const parsed = parseTemplate(template, sourceMapUrl, { preserveWhitespaces, interpolationConfig
|
|
29316
|
+
const parsed = parseTemplate(template, sourceMapUrl, { preserveWhitespaces, interpolationConfig });
|
|
28527
29317
|
if (parsed.errors !== null) {
|
|
28528
29318
|
const errors = parsed.errors.map(err => err.toString()).join(', ');
|
|
28529
29319
|
throw new Error(`Errors during JIT compilation of template for ${typeName}: ${errors}`);
|
|
@@ -28736,13 +29526,11 @@ function publishFacade(global) {
|
|
|
28736
29526
|
* @description
|
|
28737
29527
|
* Entry point for all public APIs of the compiler package.
|
|
28738
29528
|
*/
|
|
28739
|
-
const VERSION = new Version('17.0.0-next.
|
|
29529
|
+
const VERSION = new Version('17.0.0-next.8');
|
|
28740
29530
|
|
|
28741
29531
|
class CompilerConfig {
|
|
28742
|
-
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated,
|
|
29532
|
+
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
28743
29533
|
this.defaultEncapsulation = defaultEncapsulation;
|
|
28744
|
-
this.useJit = !!useJit;
|
|
28745
|
-
this.missingTranslation = missingTranslation;
|
|
28746
29534
|
this.preserveWhitespaces = preserveWhitespacesDefault(noUndefined(preserveWhitespaces));
|
|
28747
29535
|
this.strictInjectionParameters = strictInjectionParameters === true;
|
|
28748
29536
|
}
|
|
@@ -30232,6 +31020,31 @@ function compileComponentClassMetadata(metadata, deferrableTypes) {
|
|
|
30232
31020
|
return iife.callFn([]);
|
|
30233
31021
|
}
|
|
30234
31022
|
|
|
31023
|
+
/**
|
|
31024
|
+
* Generate an ngDevMode guarded call to setClassDebugInfo with the debug info about the class
|
|
31025
|
+
* (e.g., the file name in which the class is defined)
|
|
31026
|
+
*/
|
|
31027
|
+
function compileClassDebugInfo(debugInfo) {
|
|
31028
|
+
const debugInfoObject = {
|
|
31029
|
+
className: debugInfo.className,
|
|
31030
|
+
};
|
|
31031
|
+
// Include file path and line number only if the file relative path is calculated successfully.
|
|
31032
|
+
if (debugInfo.filePath) {
|
|
31033
|
+
debugInfoObject.filePath = debugInfo.filePath;
|
|
31034
|
+
debugInfoObject.lineNumber = debugInfo.lineNumber;
|
|
31035
|
+
}
|
|
31036
|
+
// Include forbidOrphanRendering only if it's set to true (to reduce generated code)
|
|
31037
|
+
if (debugInfo.forbidOrphanRendering) {
|
|
31038
|
+
debugInfoObject.forbidOrphanRendering = literal(true);
|
|
31039
|
+
}
|
|
31040
|
+
const fnCall = importExpr(Identifiers.setClassDebugInfo).callFn([
|
|
31041
|
+
debugInfo.type,
|
|
31042
|
+
mapLiteral(debugInfoObject),
|
|
31043
|
+
]);
|
|
31044
|
+
const iife = arrowFn([], [devOnlyGuardedExpression(fnCall).toStmt()]);
|
|
31045
|
+
return iife.callFn([]);
|
|
31046
|
+
}
|
|
31047
|
+
|
|
30235
31048
|
/**
|
|
30236
31049
|
* Every time we make a breaking change to the declaration interface or partial-linker behavior, we
|
|
30237
31050
|
* must update this constant to prevent old partial-linkers from incorrectly processing the
|
|
@@ -30243,7 +31056,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
|
|
|
30243
31056
|
function compileDeclareClassMetadata(metadata) {
|
|
30244
31057
|
const definitionMap = new DefinitionMap();
|
|
30245
31058
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
30246
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
31059
|
+
definitionMap.set('version', literal('17.0.0-next.8'));
|
|
30247
31060
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
30248
31061
|
definitionMap.set('type', metadata.type);
|
|
30249
31062
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -30351,7 +31164,7 @@ function createDirectiveDefinitionMap(meta) {
|
|
|
30351
31164
|
// in 16.1 is actually used.
|
|
30352
31165
|
const minVersion = hasTransformFunctions ? MINIMUM_PARTIAL_LINKER_VERSION$5 : '14.0.0';
|
|
30353
31166
|
definitionMap.set('minVersion', literal(minVersion));
|
|
30354
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
31167
|
+
definitionMap.set('version', literal('17.0.0-next.8'));
|
|
30355
31168
|
// e.g. `type: MyDirective`
|
|
30356
31169
|
definitionMap.set('type', meta.type.value);
|
|
30357
31170
|
if (meta.isStandalone) {
|
|
@@ -30477,10 +31290,17 @@ function compileDeclareComponentFromMetadata(meta, template, additionalTemplateI
|
|
|
30477
31290
|
*/
|
|
30478
31291
|
function createComponentDefinitionMap(meta, template, templateInfo) {
|
|
30479
31292
|
const definitionMap = createDirectiveDefinitionMap(meta);
|
|
31293
|
+
const blockVisitor = new BlockPresenceVisitor();
|
|
31294
|
+
visitAll$1(blockVisitor, template.nodes);
|
|
30480
31295
|
definitionMap.set('template', getTemplateExpression(template, templateInfo));
|
|
30481
31296
|
if (templateInfo.isInline) {
|
|
30482
31297
|
definitionMap.set('isInline', literal(true));
|
|
30483
31298
|
}
|
|
31299
|
+
// Set the minVersion to 17.0.0 if the component is using at least one block in its template.
|
|
31300
|
+
// We don't do this for templates without blocks, in order to preserve backwards compatibility.
|
|
31301
|
+
if (blockVisitor.hasBlocks) {
|
|
31302
|
+
definitionMap.set('minVersion', literal('17.0.0'));
|
|
31303
|
+
}
|
|
30484
31304
|
definitionMap.set('styles', toOptionalLiteralArray(meta.styles, literal));
|
|
30485
31305
|
definitionMap.set('dependencies', compileUsedDependenciesMetadata(meta));
|
|
30486
31306
|
definitionMap.set('viewProviders', meta.viewProviders);
|
|
@@ -30573,6 +31393,42 @@ function compileUsedDependenciesMetadata(meta) {
|
|
|
30573
31393
|
}
|
|
30574
31394
|
});
|
|
30575
31395
|
}
|
|
31396
|
+
class BlockPresenceVisitor extends RecursiveVisitor$1 {
|
|
31397
|
+
constructor() {
|
|
31398
|
+
super(...arguments);
|
|
31399
|
+
this.hasBlocks = false;
|
|
31400
|
+
}
|
|
31401
|
+
visitDeferredBlock() {
|
|
31402
|
+
this.hasBlocks = true;
|
|
31403
|
+
}
|
|
31404
|
+
visitDeferredBlockPlaceholder() {
|
|
31405
|
+
this.hasBlocks = true;
|
|
31406
|
+
}
|
|
31407
|
+
visitDeferredBlockLoading() {
|
|
31408
|
+
this.hasBlocks = true;
|
|
31409
|
+
}
|
|
31410
|
+
visitDeferredBlockError() {
|
|
31411
|
+
this.hasBlocks = true;
|
|
31412
|
+
}
|
|
31413
|
+
visitIfBlock() {
|
|
31414
|
+
this.hasBlocks = true;
|
|
31415
|
+
}
|
|
31416
|
+
visitIfBlockBranch() {
|
|
31417
|
+
this.hasBlocks = true;
|
|
31418
|
+
}
|
|
31419
|
+
visitForLoopBlock() {
|
|
31420
|
+
this.hasBlocks = true;
|
|
31421
|
+
}
|
|
31422
|
+
visitForLoopBlockEmpty() {
|
|
31423
|
+
this.hasBlocks = true;
|
|
31424
|
+
}
|
|
31425
|
+
visitSwitchBlock() {
|
|
31426
|
+
this.hasBlocks = true;
|
|
31427
|
+
}
|
|
31428
|
+
visitSwitchBlockCase() {
|
|
31429
|
+
this.hasBlocks = true;
|
|
31430
|
+
}
|
|
31431
|
+
}
|
|
30576
31432
|
|
|
30577
31433
|
/**
|
|
30578
31434
|
* Every time we make a breaking change to the declaration interface or partial-linker behavior, we
|
|
@@ -30585,7 +31441,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
30585
31441
|
function compileDeclareFactoryFunction(meta) {
|
|
30586
31442
|
const definitionMap = new DefinitionMap();
|
|
30587
31443
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
30588
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
31444
|
+
definitionMap.set('version', literal('17.0.0-next.8'));
|
|
30589
31445
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
30590
31446
|
definitionMap.set('type', meta.type.value);
|
|
30591
31447
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -30620,7 +31476,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
30620
31476
|
function createInjectableDefinitionMap(meta) {
|
|
30621
31477
|
const definitionMap = new DefinitionMap();
|
|
30622
31478
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
30623
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
31479
|
+
definitionMap.set('version', literal('17.0.0-next.8'));
|
|
30624
31480
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
30625
31481
|
definitionMap.set('type', meta.type.value);
|
|
30626
31482
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -30671,7 +31527,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
30671
31527
|
function createInjectorDefinitionMap(meta) {
|
|
30672
31528
|
const definitionMap = new DefinitionMap();
|
|
30673
31529
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
30674
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
31530
|
+
definitionMap.set('version', literal('17.0.0-next.8'));
|
|
30675
31531
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
30676
31532
|
definitionMap.set('type', meta.type.value);
|
|
30677
31533
|
definitionMap.set('providers', meta.providers);
|
|
@@ -30704,7 +31560,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
30704
31560
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
30705
31561
|
}
|
|
30706
31562
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
30707
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
31563
|
+
definitionMap.set('version', literal('17.0.0-next.8'));
|
|
30708
31564
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
30709
31565
|
definitionMap.set('type', meta.type.value);
|
|
30710
31566
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -30755,7 +31611,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
30755
31611
|
function createPipeDefinitionMap(meta) {
|
|
30756
31612
|
const definitionMap = new DefinitionMap();
|
|
30757
31613
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
30758
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
31614
|
+
definitionMap.set('version', literal('17.0.0-next.8'));
|
|
30759
31615
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
30760
31616
|
// e.g. `type: MyPipe`
|
|
30761
31617
|
definitionMap.set('type', meta.type.value);
|
|
@@ -30788,5 +31644,5 @@ publishFacade(_global);
|
|
|
30788
31644
|
|
|
30789
31645
|
// This file is not used to build this module. It is only used during editing
|
|
30790
31646
|
|
|
30791
|
-
export { AST, ASTWithName, ASTWithSource, AbsoluteSourceSpan, ArrayType, ArrowFunctionExpr, AstMemoryEfficientTransformer, AstTransformer, Attribute, Binary, BinaryOperator, BinaryOperatorExpr, BindingPipe, Block, 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 };
|
|
31647
|
+
export { AST, ASTWithName, ASTWithSource, AbsoluteSourceSpan, ArrayType, ArrowFunctionExpr, AstMemoryEfficientTransformer, AstTransformer, Attribute, Binary, BinaryOperator, BinaryOperatorExpr, BindingPipe, Block, 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, UnknownBlock as TmplAstUnknownBlock, 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, compileClassDebugInfo, 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, literal, literalMap, makeBindingParser, mergeNsAndName, output_ast as outputAst, parseHostBindings, parseTemplate, preserveWhitespacesDefault, publishFacade, r3JitTypeSourceSpan, sanitizeIdentifier, splitNsName, verifyHostBindings, visitAll };
|
|
30792
31648
|
//# sourceMappingURL=compiler.mjs.map
|