@angular/compiler 17.0.3 → 17.0.5
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 +2 -3
- package/esm2022/src/expression_parser/parser.mjs +2 -2
- package/esm2022/src/i18n/digest.mjs +4 -1
- package/esm2022/src/i18n/extractor_merger.mjs +4 -2
- package/esm2022/src/i18n/i18n_ast.mjs +27 -1
- package/esm2022/src/i18n/i18n_html_parser.mjs +2 -2
- package/esm2022/src/i18n/i18n_parser.mjs +23 -6
- package/esm2022/src/i18n/message_bundle.mjs +7 -1
- package/esm2022/src/i18n/serializers/placeholder.mjs +29 -1
- package/esm2022/src/i18n/serializers/serializer.mjs +6 -1
- package/esm2022/src/i18n/serializers/xliff.mjs +7 -1
- package/esm2022/src/i18n/serializers/xliff2.mjs +19 -1
- package/esm2022/src/i18n/serializers/xmb.mjs +12 -1
- package/esm2022/src/i18n/translation_bundle.mjs +6 -1
- package/esm2022/src/jit_compiler_facade.mjs +2 -2
- package/esm2022/src/ml_parser/ast.mjs +4 -4
- package/esm2022/src/ml_parser/defaults.mjs +24 -0
- package/esm2022/src/ml_parser/lexer.mjs +2 -2
- package/esm2022/src/render3/partial/class_metadata.mjs +1 -1
- package/esm2022/src/render3/partial/component.mjs +2 -2
- 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 +17 -9
- package/esm2022/src/render3/r3_control_flow.mjs +7 -7
- package/esm2022/src/render3/r3_deferred_blocks.mjs +5 -5
- package/esm2022/src/render3/view/api.mjs +1 -1
- package/esm2022/src/render3/view/compiler.mjs +6 -4
- package/esm2022/src/render3/view/i18n/context.mjs +13 -1
- package/esm2022/src/render3/view/i18n/get_msg_utils.mjs +4 -1
- package/esm2022/src/render3/view/i18n/icu_serializer.mjs +4 -1
- package/esm2022/src/render3/view/i18n/localize_utils.mjs +6 -1
- package/esm2022/src/render3/view/i18n/meta.mjs +5 -4
- package/esm2022/src/render3/view/template.mjs +79 -33
- package/esm2022/src/template/pipeline/ir/src/enums.mjs +9 -1
- package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +3 -2
- package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +2 -1
- package/esm2022/src/template/pipeline/src/emit.mjs +1 -3
- package/esm2022/src/template/pipeline/src/instruction.mjs +3 -3
- package/esm2022/src/template/pipeline/src/phases/assign_i18n_slot_dependencies.mjs +2 -7
- package/esm2022/src/template/pipeline/src/phases/create_i18n_contexts.mjs +20 -6
- package/esm2022/src/template/pipeline/src/phases/extract_i18n_messages.mjs +94 -23
- package/esm2022/src/template/pipeline/src/phases/propagate_i18n_blocks.mjs +3 -2
- package/esm2022/src/template/pipeline/src/phases/reify.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_element_placeholders.mjs +70 -57
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_expression_placeholders.mjs +4 -4
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_icu_placeholders.mjs +16 -25
- package/esm2022/src/template_parser/binding_parser.mjs +1 -1
- package/esm2022/src/version.mjs +1 -1
- package/fesm2022/compiler.mjs +494 -245
- package/fesm2022/compiler.mjs.map +1 -1
- package/index.d.ts +36 -12
- package/package.json +2 -2
- package/esm2022/src/ml_parser/interpolation_config.mjs +0 -23
- package/esm2022/src/template/pipeline/src/phases/merge_i18n_contexts.mjs +0 -59
package/fesm2022/compiler.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v17.0.
|
|
2
|
+
* @license Angular v17.0.5
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -539,6 +539,9 @@ class _SerializerVisitor {
|
|
|
539
539
|
visitIcuPlaceholder(ph, context) {
|
|
540
540
|
return `<ph icu name="${ph.name}">${ph.value.visit(this)}</ph>`;
|
|
541
541
|
}
|
|
542
|
+
visitBlockPlaceholder(ph, context) {
|
|
543
|
+
return `<ph block name="${ph.startName}">${ph.children.map(child => child.visit(this)).join(', ')}</ph name="${ph.closeName}">`;
|
|
544
|
+
}
|
|
542
545
|
}
|
|
543
546
|
const serializerVisitor$1 = new _SerializerVisitor();
|
|
544
547
|
function serializeNodes(nodes) {
|
|
@@ -3847,43 +3850,47 @@ class BlockNode {
|
|
|
3847
3850
|
}
|
|
3848
3851
|
}
|
|
3849
3852
|
class DeferredBlockPlaceholder extends BlockNode {
|
|
3850
|
-
constructor(children, minimumTime, nameSpan, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3853
|
+
constructor(children, minimumTime, nameSpan, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
3851
3854
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3852
3855
|
this.children = children;
|
|
3853
3856
|
this.minimumTime = minimumTime;
|
|
3857
|
+
this.i18n = i18n;
|
|
3854
3858
|
}
|
|
3855
3859
|
visit(visitor) {
|
|
3856
3860
|
return visitor.visitDeferredBlockPlaceholder(this);
|
|
3857
3861
|
}
|
|
3858
3862
|
}
|
|
3859
3863
|
class DeferredBlockLoading extends BlockNode {
|
|
3860
|
-
constructor(children, afterTime, minimumTime, nameSpan, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3864
|
+
constructor(children, afterTime, minimumTime, nameSpan, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
3861
3865
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3862
3866
|
this.children = children;
|
|
3863
3867
|
this.afterTime = afterTime;
|
|
3864
3868
|
this.minimumTime = minimumTime;
|
|
3869
|
+
this.i18n = i18n;
|
|
3865
3870
|
}
|
|
3866
3871
|
visit(visitor) {
|
|
3867
3872
|
return visitor.visitDeferredBlockLoading(this);
|
|
3868
3873
|
}
|
|
3869
3874
|
}
|
|
3870
3875
|
class DeferredBlockError extends BlockNode {
|
|
3871
|
-
constructor(children, nameSpan, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3876
|
+
constructor(children, nameSpan, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
3872
3877
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3873
3878
|
this.children = children;
|
|
3879
|
+
this.i18n = i18n;
|
|
3874
3880
|
}
|
|
3875
3881
|
visit(visitor) {
|
|
3876
3882
|
return visitor.visitDeferredBlockError(this);
|
|
3877
3883
|
}
|
|
3878
3884
|
}
|
|
3879
3885
|
class DeferredBlock extends BlockNode {
|
|
3880
|
-
constructor(children, triggers, prefetchTriggers, placeholder, loading, error, nameSpan, sourceSpan, mainBlockSpan, startSourceSpan, endSourceSpan) {
|
|
3886
|
+
constructor(children, triggers, prefetchTriggers, placeholder, loading, error, nameSpan, sourceSpan, mainBlockSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
3881
3887
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3882
3888
|
this.children = children;
|
|
3883
3889
|
this.placeholder = placeholder;
|
|
3884
3890
|
this.loading = loading;
|
|
3885
3891
|
this.error = error;
|
|
3886
3892
|
this.mainBlockSpan = mainBlockSpan;
|
|
3893
|
+
this.i18n = i18n;
|
|
3887
3894
|
this.triggers = triggers;
|
|
3888
3895
|
this.prefetchTriggers = prefetchTriggers;
|
|
3889
3896
|
// We cache the keys since we know that they won't change and we
|
|
@@ -3922,17 +3929,18 @@ class SwitchBlock extends BlockNode {
|
|
|
3922
3929
|
}
|
|
3923
3930
|
}
|
|
3924
3931
|
class SwitchBlockCase extends BlockNode {
|
|
3925
|
-
constructor(expression, children, sourceSpan, startSourceSpan, endSourceSpan, nameSpan) {
|
|
3932
|
+
constructor(expression, children, sourceSpan, startSourceSpan, endSourceSpan, nameSpan, i18n) {
|
|
3926
3933
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3927
3934
|
this.expression = expression;
|
|
3928
3935
|
this.children = children;
|
|
3936
|
+
this.i18n = i18n;
|
|
3929
3937
|
}
|
|
3930
3938
|
visit(visitor) {
|
|
3931
3939
|
return visitor.visitSwitchBlockCase(this);
|
|
3932
3940
|
}
|
|
3933
3941
|
}
|
|
3934
3942
|
class ForLoopBlock extends BlockNode {
|
|
3935
|
-
constructor(item, expression, trackBy, trackKeywordSpan, contextVariables, children, empty, sourceSpan, mainBlockSpan, startSourceSpan, endSourceSpan, nameSpan) {
|
|
3943
|
+
constructor(item, expression, trackBy, trackKeywordSpan, contextVariables, children, empty, sourceSpan, mainBlockSpan, startSourceSpan, endSourceSpan, nameSpan, i18n) {
|
|
3936
3944
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3937
3945
|
this.item = item;
|
|
3938
3946
|
this.expression = expression;
|
|
@@ -3942,15 +3950,17 @@ class ForLoopBlock extends BlockNode {
|
|
|
3942
3950
|
this.children = children;
|
|
3943
3951
|
this.empty = empty;
|
|
3944
3952
|
this.mainBlockSpan = mainBlockSpan;
|
|
3953
|
+
this.i18n = i18n;
|
|
3945
3954
|
}
|
|
3946
3955
|
visit(visitor) {
|
|
3947
3956
|
return visitor.visitForLoopBlock(this);
|
|
3948
3957
|
}
|
|
3949
3958
|
}
|
|
3950
3959
|
class ForLoopBlockEmpty extends BlockNode {
|
|
3951
|
-
constructor(children, sourceSpan, startSourceSpan, endSourceSpan, nameSpan) {
|
|
3960
|
+
constructor(children, sourceSpan, startSourceSpan, endSourceSpan, nameSpan, i18n) {
|
|
3952
3961
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3953
3962
|
this.children = children;
|
|
3963
|
+
this.i18n = i18n;
|
|
3954
3964
|
}
|
|
3955
3965
|
visit(visitor) {
|
|
3956
3966
|
return visitor.visitForLoopBlockEmpty(this);
|
|
@@ -3966,11 +3976,12 @@ class IfBlock extends BlockNode {
|
|
|
3966
3976
|
}
|
|
3967
3977
|
}
|
|
3968
3978
|
class IfBlockBranch extends BlockNode {
|
|
3969
|
-
constructor(expression, children, expressionAlias, sourceSpan, startSourceSpan, endSourceSpan, nameSpan) {
|
|
3979
|
+
constructor(expression, children, expressionAlias, sourceSpan, startSourceSpan, endSourceSpan, nameSpan, i18n) {
|
|
3970
3980
|
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
|
|
3971
3981
|
this.expression = expression;
|
|
3972
3982
|
this.children = children;
|
|
3973
3983
|
this.expressionAlias = expressionAlias;
|
|
3984
|
+
this.i18n = i18n;
|
|
3974
3985
|
}
|
|
3975
3986
|
visit(visitor) {
|
|
3976
3987
|
return visitor.visitIfBlockBranch(this);
|
|
@@ -4240,6 +4251,21 @@ class IcuPlaceholder {
|
|
|
4240
4251
|
return visitor.visitIcuPlaceholder(this, context);
|
|
4241
4252
|
}
|
|
4242
4253
|
}
|
|
4254
|
+
class BlockPlaceholder {
|
|
4255
|
+
constructor(name, parameters, startName, closeName, children, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
4256
|
+
this.name = name;
|
|
4257
|
+
this.parameters = parameters;
|
|
4258
|
+
this.startName = startName;
|
|
4259
|
+
this.closeName = closeName;
|
|
4260
|
+
this.children = children;
|
|
4261
|
+
this.sourceSpan = sourceSpan;
|
|
4262
|
+
this.startSourceSpan = startSourceSpan;
|
|
4263
|
+
this.endSourceSpan = endSourceSpan;
|
|
4264
|
+
}
|
|
4265
|
+
visit(visitor, context) {
|
|
4266
|
+
return visitor.visitBlockPlaceholder(this, context);
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
4243
4269
|
// Clone the AST
|
|
4244
4270
|
class CloneVisitor {
|
|
4245
4271
|
visitText(text, context) {
|
|
@@ -4265,6 +4291,10 @@ class CloneVisitor {
|
|
|
4265
4291
|
visitIcuPlaceholder(ph, context) {
|
|
4266
4292
|
return new IcuPlaceholder(ph.value, ph.name, ph.sourceSpan);
|
|
4267
4293
|
}
|
|
4294
|
+
visitBlockPlaceholder(ph, context) {
|
|
4295
|
+
const children = ph.children.map(n => n.visit(this, context));
|
|
4296
|
+
return new BlockPlaceholder(ph.name, ph.parameters, ph.startName, ph.closeName, children, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan);
|
|
4297
|
+
}
|
|
4268
4298
|
}
|
|
4269
4299
|
// Visit all the nodes recursively
|
|
4270
4300
|
class RecurseVisitor {
|
|
@@ -4282,6 +4312,9 @@ class RecurseVisitor {
|
|
|
4282
4312
|
}
|
|
4283
4313
|
visitPlaceholder(ph, context) { }
|
|
4284
4314
|
visitIcuPlaceholder(ph, context) { }
|
|
4315
|
+
visitBlockPlaceholder(ph, context) {
|
|
4316
|
+
ph.children.forEach(child => child.visit(this));
|
|
4317
|
+
}
|
|
4285
4318
|
}
|
|
4286
4319
|
/**
|
|
4287
4320
|
* Serialize the message to the Localize backtick string format that would appear in compiled code.
|
|
@@ -4312,6 +4345,10 @@ class LocalizeMessageStringVisitor {
|
|
|
4312
4345
|
visitIcuPlaceholder(ph) {
|
|
4313
4346
|
return `{$${ph.name}}`;
|
|
4314
4347
|
}
|
|
4348
|
+
visitBlockPlaceholder(ph) {
|
|
4349
|
+
const children = ph.children.map(child => child.visit(this)).join('');
|
|
4350
|
+
return `{$${ph.startName}}${children}{$${ph.closeName}}`;
|
|
4351
|
+
}
|
|
4315
4352
|
}
|
|
4316
4353
|
|
|
4317
4354
|
class Serializer {
|
|
@@ -4354,6 +4391,11 @@ class SimplePlaceholderMapper extends RecurseVisitor {
|
|
|
4354
4391
|
visitPlaceholder(ph, context) {
|
|
4355
4392
|
this.visitPlaceholderName(ph.name);
|
|
4356
4393
|
}
|
|
4394
|
+
visitBlockPlaceholder(ph, context) {
|
|
4395
|
+
this.visitPlaceholderName(ph.startName);
|
|
4396
|
+
super.visitBlockPlaceholder(ph, context);
|
|
4397
|
+
this.visitPlaceholderName(ph.closeName);
|
|
4398
|
+
}
|
|
4357
4399
|
visitIcuPlaceholder(ph, context) {
|
|
4358
4400
|
this.visitPlaceholderName(ph.name);
|
|
4359
4401
|
}
|
|
@@ -4566,6 +4608,17 @@ class _Visitor$1 {
|
|
|
4566
4608
|
new Tag(_PLACEHOLDER_TAG$3, { name: ph.name }, [exTag, interpolationAsText])
|
|
4567
4609
|
];
|
|
4568
4610
|
}
|
|
4611
|
+
visitBlockPlaceholder(ph, context) {
|
|
4612
|
+
const startAsText = new Text$1(`@${ph.name}`);
|
|
4613
|
+
const startEx = new Tag(_EXAMPLE_TAG, {}, [startAsText]);
|
|
4614
|
+
// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
|
|
4615
|
+
const startTagPh = new Tag(_PLACEHOLDER_TAG$3, { name: ph.startName }, [startEx, startAsText]);
|
|
4616
|
+
const closeAsText = new Text$1(`}`);
|
|
4617
|
+
const closeEx = new Tag(_EXAMPLE_TAG, {}, [closeAsText]);
|
|
4618
|
+
// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
|
|
4619
|
+
const closeTagPh = new Tag(_PLACEHOLDER_TAG$3, { name: ph.closeName }, [closeEx, closeAsText]);
|
|
4620
|
+
return [startTagPh, ...this.serialize(ph.children), closeTagPh];
|
|
4621
|
+
}
|
|
4569
4622
|
visitIcuPlaceholder(ph, context) {
|
|
4570
4623
|
const icuExpression = ph.value.expression;
|
|
4571
4624
|
const icuType = ph.value.type;
|
|
@@ -5211,6 +5264,7 @@ class InterpolationConfig {
|
|
|
5211
5264
|
}
|
|
5212
5265
|
}
|
|
5213
5266
|
const DEFAULT_INTERPOLATION_CONFIG = new InterpolationConfig('{{', '}}');
|
|
5267
|
+
const DEFAULT_CONTAINER_BLOCKS = new Set(['switch']);
|
|
5214
5268
|
|
|
5215
5269
|
const $EOF = 0;
|
|
5216
5270
|
const $BSPACE = 8;
|
|
@@ -9141,6 +9195,14 @@ var DerivedRepeaterVarIdentity;
|
|
|
9141
9195
|
DerivedRepeaterVarIdentity[DerivedRepeaterVarIdentity["Even"] = 2] = "Even";
|
|
9142
9196
|
DerivedRepeaterVarIdentity[DerivedRepeaterVarIdentity["Odd"] = 3] = "Odd";
|
|
9143
9197
|
})(DerivedRepeaterVarIdentity || (DerivedRepeaterVarIdentity = {}));
|
|
9198
|
+
/**
|
|
9199
|
+
* Kinds of i18n contexts. They can be created because of root i18n blocks, or ICUs.
|
|
9200
|
+
*/
|
|
9201
|
+
var I18nContextKind;
|
|
9202
|
+
(function (I18nContextKind) {
|
|
9203
|
+
I18nContextKind[I18nContextKind["RootI18n"] = 0] = "RootI18n";
|
|
9204
|
+
I18nContextKind[I18nContextKind["Icu"] = 1] = "Icu";
|
|
9205
|
+
})(I18nContextKind || (I18nContextKind = {}));
|
|
9144
9206
|
|
|
9145
9207
|
/**
|
|
9146
9208
|
* Marker symbol for `ConsumesSlotOpTrait`.
|
|
@@ -9414,6 +9476,7 @@ function createRepeaterOp(repeaterCreate, targetSlot, collection, sourceSpan) {
|
|
|
9414
9476
|
collection,
|
|
9415
9477
|
sourceSpan,
|
|
9416
9478
|
...NEW_OP,
|
|
9479
|
+
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9417
9480
|
};
|
|
9418
9481
|
}
|
|
9419
9482
|
function createDeferWhenOp(target, expr, prefetch, sourceSpan) {
|
|
@@ -10924,9 +10987,10 @@ function createIcuEndOp(xref) {
|
|
|
10924
10987
|
...NEW_OP,
|
|
10925
10988
|
};
|
|
10926
10989
|
}
|
|
10927
|
-
function createI18nContextOp(xref, i18nBlock, message, sourceSpan) {
|
|
10990
|
+
function createI18nContextOp(contextKind, xref, i18nBlock, message, sourceSpan) {
|
|
10928
10991
|
return {
|
|
10929
10992
|
kind: OpKind.I18nContext,
|
|
10993
|
+
contextKind,
|
|
10930
10994
|
xref,
|
|
10931
10995
|
i18nBlock,
|
|
10932
10996
|
message,
|
|
@@ -11212,7 +11276,6 @@ function needsApplication(i18nContexts, op) {
|
|
|
11212
11276
|
*/
|
|
11213
11277
|
function assignI18nSlotDependencies(job) {
|
|
11214
11278
|
const i18nLastSlotConsumers = new Map();
|
|
11215
|
-
const i18nContexts = new Map();
|
|
11216
11279
|
let lastSlotConsumer = null;
|
|
11217
11280
|
let currentI18nOp = null;
|
|
11218
11281
|
for (const unit of job.units) {
|
|
@@ -11229,16 +11292,12 @@ function assignI18nSlotDependencies(job) {
|
|
|
11229
11292
|
i18nLastSlotConsumers.set(currentI18nOp.xref, lastSlotConsumer);
|
|
11230
11293
|
currentI18nOp = null;
|
|
11231
11294
|
break;
|
|
11232
|
-
case OpKind.I18nContext:
|
|
11233
|
-
i18nContexts.set(op.xref, op);
|
|
11234
|
-
break;
|
|
11235
11295
|
}
|
|
11236
11296
|
}
|
|
11237
11297
|
// Assign i18n expressions to target the last slot in its owning block.
|
|
11238
11298
|
for (const op of unit.update) {
|
|
11239
11299
|
if (op.kind === OpKind.I18nExpression) {
|
|
11240
|
-
|
|
11241
|
-
op.target = i18nLastSlotConsumers.get(i18nContext.i18nBlock);
|
|
11300
|
+
op.target = i18nLastSlotConsumers.get(op.target);
|
|
11242
11301
|
}
|
|
11243
11302
|
}
|
|
11244
11303
|
}
|
|
@@ -11847,17 +11906,22 @@ function createDeferDepsFns(job) {
|
|
|
11847
11906
|
* message.)
|
|
11848
11907
|
*/
|
|
11849
11908
|
function createI18nContexts(job) {
|
|
11909
|
+
const rootContexts = new Map();
|
|
11850
11910
|
let currentI18nOp = null;
|
|
11851
11911
|
let xref;
|
|
11852
11912
|
for (const unit of job.units) {
|
|
11853
11913
|
for (const op of unit.create) {
|
|
11854
11914
|
switch (op.kind) {
|
|
11855
11915
|
case OpKind.I18nStart:
|
|
11856
|
-
// Each i18n block gets its own context.
|
|
11857
|
-
xref = job.allocateXrefId();
|
|
11858
|
-
unit.create.push(createI18nContextOp(xref, op.xref, op.message, null));
|
|
11859
|
-
op.context = xref;
|
|
11860
11916
|
currentI18nOp = op;
|
|
11917
|
+
// Each root i18n block gets its own context, child ones refer to the context for their
|
|
11918
|
+
// root block.
|
|
11919
|
+
if (op.xref === op.root) {
|
|
11920
|
+
xref = job.allocateXrefId();
|
|
11921
|
+
unit.create.push(createI18nContextOp(I18nContextKind.RootI18n, xref, op.xref, op.message, null));
|
|
11922
|
+
op.context = xref;
|
|
11923
|
+
rootContexts.set(op.xref, xref);
|
|
11924
|
+
}
|
|
11861
11925
|
break;
|
|
11862
11926
|
case OpKind.I18nEnd:
|
|
11863
11927
|
currentI18nOp = null;
|
|
@@ -11871,7 +11935,7 @@ function createI18nContexts(job) {
|
|
|
11871
11935
|
if (op.message.id !== currentI18nOp.message.id) {
|
|
11872
11936
|
// There was an enclosing i18n block around this ICU somewhere.
|
|
11873
11937
|
xref = job.allocateXrefId();
|
|
11874
|
-
unit.create.push(createI18nContextOp(xref, currentI18nOp.xref, op.message, null));
|
|
11938
|
+
unit.create.push(createI18nContextOp(I18nContextKind.Icu, xref, currentI18nOp.xref, op.message, null));
|
|
11875
11939
|
op.context = xref;
|
|
11876
11940
|
}
|
|
11877
11941
|
else {
|
|
@@ -11883,6 +11947,15 @@ function createI18nContexts(job) {
|
|
|
11883
11947
|
}
|
|
11884
11948
|
}
|
|
11885
11949
|
}
|
|
11950
|
+
// Assign contexts to child i18n blocks, now that all root i18n blocks have their context
|
|
11951
|
+
// assigned.
|
|
11952
|
+
for (const unit of job.units) {
|
|
11953
|
+
for (const op of unit.create) {
|
|
11954
|
+
if (op.kind === OpKind.I18nStart && op.xref !== op.root) {
|
|
11955
|
+
op.context = rootContexts.get(op.root);
|
|
11956
|
+
}
|
|
11957
|
+
}
|
|
11958
|
+
}
|
|
11886
11959
|
}
|
|
11887
11960
|
|
|
11888
11961
|
/**
|
|
@@ -12265,11 +12338,9 @@ const LIST_DELIMITER = '|';
|
|
|
12265
12338
|
* used in the final output.
|
|
12266
12339
|
*/
|
|
12267
12340
|
function extractI18nMessages(job) {
|
|
12268
|
-
// Save the i18n context ops for later use.
|
|
12341
|
+
// Save the i18n start and i18n context ops for later use.
|
|
12269
12342
|
const i18nContexts = new Map();
|
|
12270
|
-
|
|
12271
|
-
// created from ICUs).
|
|
12272
|
-
const i18nBlockContexts = new Set();
|
|
12343
|
+
const i18nBlocks = new Map();
|
|
12273
12344
|
for (const unit of job.units) {
|
|
12274
12345
|
for (const op of unit.create) {
|
|
12275
12346
|
switch (op.kind) {
|
|
@@ -12277,7 +12348,7 @@ function extractI18nMessages(job) {
|
|
|
12277
12348
|
i18nContexts.set(op.xref, op);
|
|
12278
12349
|
break;
|
|
12279
12350
|
case OpKind.I18nStart:
|
|
12280
|
-
|
|
12351
|
+
i18nBlocks.set(op.xref, op);
|
|
12281
12352
|
break;
|
|
12282
12353
|
}
|
|
12283
12354
|
}
|
|
@@ -12304,11 +12375,12 @@ function extractI18nMessages(job) {
|
|
|
12304
12375
|
if (!op.context) {
|
|
12305
12376
|
throw Error('ICU op should have its context set.');
|
|
12306
12377
|
}
|
|
12307
|
-
|
|
12308
|
-
|
|
12378
|
+
const i18nContext = i18nContexts.get(op.context);
|
|
12379
|
+
if (i18nContext.contextKind === I18nContextKind.Icu) {
|
|
12309
12380
|
const subMessage = createI18nMessage(job, i18nContext, op.messagePlaceholder);
|
|
12310
12381
|
unit.create.push(subMessage);
|
|
12311
|
-
const
|
|
12382
|
+
const rootI18nId = i18nBlocks.get(i18nContext.i18nBlock).root;
|
|
12383
|
+
const parentMessage = i18nBlockMessages.get(rootI18nId);
|
|
12312
12384
|
parentMessage?.subMessages.push(subMessage.xref);
|
|
12313
12385
|
}
|
|
12314
12386
|
OpList.remove(op);
|
|
@@ -12324,38 +12396,110 @@ function extractI18nMessages(job) {
|
|
|
12324
12396
|
* Create an i18n message op from an i18n context op.
|
|
12325
12397
|
*/
|
|
12326
12398
|
function createI18nMessage(job, context, messagePlaceholder) {
|
|
12327
|
-
let needsPostprocessing = context.
|
|
12328
|
-
|
|
12329
|
-
|
|
12330
|
-
|
|
12331
|
-
}
|
|
12332
|
-
}
|
|
12333
|
-
return createI18nMessageOp(job.allocateXrefId(), context.i18nBlock, context.message, messagePlaceholder ?? null, formatParams(context.params), formatParams(context.postprocessingParams), needsPostprocessing);
|
|
12399
|
+
let [formattedParams, needsPostprocessing] = formatParams(context.params);
|
|
12400
|
+
const [formattedPostprocessingParams] = formatParams(context.postprocessingParams);
|
|
12401
|
+
needsPostprocessing ||= formattedPostprocessingParams.size > 0;
|
|
12402
|
+
return createI18nMessageOp(job.allocateXrefId(), context.i18nBlock, context.message, messagePlaceholder ?? null, formattedParams, formattedPostprocessingParams, needsPostprocessing);
|
|
12334
12403
|
}
|
|
12335
12404
|
/**
|
|
12336
12405
|
* Formats a map of `I18nParamValue[]` values into a map of `Expression` values.
|
|
12406
|
+
* @return A tuple of the formatted params and a boolean indicating whether postprocessing is needed
|
|
12407
|
+
* for any of the params
|
|
12337
12408
|
*/
|
|
12338
12409
|
function formatParams(params) {
|
|
12339
|
-
const
|
|
12410
|
+
const formattedParams = new Map();
|
|
12411
|
+
let needsPostprocessing = false;
|
|
12340
12412
|
for (const [placeholder, placeholderValues] of params) {
|
|
12341
|
-
const serializedValues = formatParamValues(placeholderValues);
|
|
12413
|
+
const [serializedValues, paramNeedsPostprocessing] = formatParamValues(placeholderValues);
|
|
12414
|
+
needsPostprocessing ||= paramNeedsPostprocessing;
|
|
12342
12415
|
if (serializedValues !== null) {
|
|
12343
|
-
|
|
12416
|
+
formattedParams.set(placeholder, literal(serializedValues));
|
|
12344
12417
|
}
|
|
12345
12418
|
}
|
|
12346
|
-
return
|
|
12419
|
+
return [formattedParams, needsPostprocessing];
|
|
12347
12420
|
}
|
|
12348
12421
|
/**
|
|
12349
12422
|
* Formats an `I18nParamValue[]` into a string (or null for empty array).
|
|
12423
|
+
* @return A tuple of the formatted value and a boolean indicating whether postprocessing is needed
|
|
12424
|
+
* for the value
|
|
12350
12425
|
*/
|
|
12351
12426
|
function formatParamValues(values) {
|
|
12352
12427
|
if (values.length === 0) {
|
|
12353
|
-
return null;
|
|
12428
|
+
return [null, false];
|
|
12354
12429
|
}
|
|
12430
|
+
collapseElementTemplatePairs(values);
|
|
12355
12431
|
const serializedValues = values.map(value => formatValue(value));
|
|
12356
12432
|
return serializedValues.length === 1 ?
|
|
12357
|
-
serializedValues[0] :
|
|
12358
|
-
`${LIST_START_MARKER}${serializedValues.join(LIST_DELIMITER)}${LIST_END_MARKER}
|
|
12433
|
+
[serializedValues[0], false] :
|
|
12434
|
+
[`${LIST_START_MARKER}${serializedValues.join(LIST_DELIMITER)}${LIST_END_MARKER}`, true];
|
|
12435
|
+
}
|
|
12436
|
+
/**
|
|
12437
|
+
* Collapses element/template pairs that refer to the same subTemplateIndex, i.e. elements and
|
|
12438
|
+
* templates that refer to the same element instance.
|
|
12439
|
+
*
|
|
12440
|
+
* This accounts for the case of a structural directive inside an i18n block, e.g.:
|
|
12441
|
+
* ```
|
|
12442
|
+
* <div i18n>
|
|
12443
|
+
* <div *ngIf="condition">
|
|
12444
|
+
* </div>
|
|
12445
|
+
* ```
|
|
12446
|
+
*
|
|
12447
|
+
* In this case, both the element start and template start placeholders are the same,
|
|
12448
|
+
* and we collapse them down into a single compound placeholder value. Rather than produce
|
|
12449
|
+
* `[\uFFFD#1:1\uFFFD|\uFFFD*2:1\uFFFD]`, we want to produce `\uFFFD#1:1\uFFFD\uFFFD*2:1\uFFFD`,
|
|
12450
|
+
* likewise for the closing of the element/template.
|
|
12451
|
+
*/
|
|
12452
|
+
function collapseElementTemplatePairs(values) {
|
|
12453
|
+
// Record the indicies of element and template values in the values array by subTemplateIndex.
|
|
12454
|
+
const valueIndiciesBySubTemplateIndex = new Map();
|
|
12455
|
+
for (let i = 0; i < values.length; i++) {
|
|
12456
|
+
const value = values[i];
|
|
12457
|
+
if (value.subTemplateIndex !== null &&
|
|
12458
|
+
(value.flags & (I18nParamValueFlags.ElementTag | I18nParamValueFlags.TemplateTag))) {
|
|
12459
|
+
const valueIndicies = valueIndiciesBySubTemplateIndex.get(value.subTemplateIndex) ?? [];
|
|
12460
|
+
valueIndicies.push(i);
|
|
12461
|
+
valueIndiciesBySubTemplateIndex.set(value.subTemplateIndex, valueIndicies);
|
|
12462
|
+
}
|
|
12463
|
+
}
|
|
12464
|
+
// For each subTemplateIndex, check if any values can be collapsed.
|
|
12465
|
+
for (const [subTemplateIndex, valueIndicies] of valueIndiciesBySubTemplateIndex) {
|
|
12466
|
+
if (valueIndicies.length > 1) {
|
|
12467
|
+
const elementIndex = valueIndicies.find(index => values[index].flags & I18nParamValueFlags.ElementTag);
|
|
12468
|
+
const templateIndex = valueIndicies.find(index => values[index].flags & I18nParamValueFlags.TemplateTag);
|
|
12469
|
+
// If the values list contains both an element and template value, we can collapse.
|
|
12470
|
+
if (elementIndex !== undefined && templateIndex !== undefined) {
|
|
12471
|
+
const elementValue = values[elementIndex];
|
|
12472
|
+
const templateValue = values[templateIndex];
|
|
12473
|
+
// To match the TemplateDefinitionBuilder output, flip the order depending on whether the
|
|
12474
|
+
// values represent a closing or opening tag (or both).
|
|
12475
|
+
// TODO(mmalerba): Figure out if this makes a difference in terms of either functionality,
|
|
12476
|
+
// or the resulting message ID. If not, we can remove the special-casing in the future.
|
|
12477
|
+
let compundValue;
|
|
12478
|
+
if ((elementValue.flags & I18nParamValueFlags.OpenTag) &&
|
|
12479
|
+
(elementValue.flags & I18nParamValueFlags.CloseTag)) {
|
|
12480
|
+
// TODO(mmalerba): Is this a TDB bug? I don't understand why it would put the template
|
|
12481
|
+
// value twice.
|
|
12482
|
+
compundValue = `${formatValue(templateValue)}${formatValue(elementValue)}${formatValue(templateValue)}`;
|
|
12483
|
+
}
|
|
12484
|
+
else if (elementValue.flags & I18nParamValueFlags.OpenTag) {
|
|
12485
|
+
compundValue = `${formatValue(templateValue)}${formatValue(elementValue)}`;
|
|
12486
|
+
}
|
|
12487
|
+
else {
|
|
12488
|
+
compundValue = `${formatValue(elementValue)}${formatValue(templateValue)}`;
|
|
12489
|
+
}
|
|
12490
|
+
// Replace the element value with the combined value.
|
|
12491
|
+
values.splice(elementIndex, 1, { value: compundValue, subTemplateIndex, flags: I18nParamValueFlags.None });
|
|
12492
|
+
// Replace the template value with null to preserve the indicies we calculated earlier.
|
|
12493
|
+
values.splice(templateIndex, 1, null);
|
|
12494
|
+
}
|
|
12495
|
+
}
|
|
12496
|
+
}
|
|
12497
|
+
// Strip out any nulled out values we introduced above.
|
|
12498
|
+
for (let i = values.length - 1; i >= 0; i--) {
|
|
12499
|
+
if (values[i] === null) {
|
|
12500
|
+
values.splice(i, 1);
|
|
12501
|
+
}
|
|
12502
|
+
}
|
|
12359
12503
|
}
|
|
12360
12504
|
/**
|
|
12361
12505
|
* Formats a single `I18nParamValue` into a string
|
|
@@ -12723,6 +12867,9 @@ class IcuSerializerVisitor {
|
|
|
12723
12867
|
visitPlaceholder(ph) {
|
|
12724
12868
|
return this.formatPh(ph.name);
|
|
12725
12869
|
}
|
|
12870
|
+
visitBlockPlaceholder(ph) {
|
|
12871
|
+
return `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`;
|
|
12872
|
+
}
|
|
12726
12873
|
visitIcuPlaceholder(ph, context) {
|
|
12727
12874
|
return this.formatPh(ph.name);
|
|
12728
12875
|
}
|
|
@@ -14446,12 +14593,12 @@ class Comment {
|
|
|
14446
14593
|
return visitor.visitComment(this, context);
|
|
14447
14594
|
}
|
|
14448
14595
|
}
|
|
14449
|
-
class Block {
|
|
14450
|
-
constructor(name, parameters, children, sourceSpan, nameSpan, startSourceSpan, endSourceSpan = null) {
|
|
14596
|
+
class Block extends NodeWithI18n {
|
|
14597
|
+
constructor(name, parameters, children, sourceSpan, nameSpan, startSourceSpan, endSourceSpan = null, i18n) {
|
|
14598
|
+
super(sourceSpan, i18n);
|
|
14451
14599
|
this.name = name;
|
|
14452
14600
|
this.parameters = parameters;
|
|
14453
14601
|
this.children = children;
|
|
14454
|
-
this.sourceSpan = sourceSpan;
|
|
14455
14602
|
this.nameSpan = nameSpan;
|
|
14456
14603
|
this.startSourceSpan = startSourceSpan;
|
|
14457
14604
|
this.endSourceSpan = endSourceSpan;
|
|
@@ -15137,6 +15284,24 @@ class PlaceholderRegistry {
|
|
|
15137
15284
|
getUniquePlaceholder(name) {
|
|
15138
15285
|
return this._generateUniqueName(name.toUpperCase());
|
|
15139
15286
|
}
|
|
15287
|
+
getStartBlockPlaceholderName(name, parameters) {
|
|
15288
|
+
const signature = this._hashBlock(name, parameters);
|
|
15289
|
+
if (this._signatureToName[signature]) {
|
|
15290
|
+
return this._signatureToName[signature];
|
|
15291
|
+
}
|
|
15292
|
+
const placeholder = this._generateUniqueName(`START_BLOCK_${this._toSnakeCase(name)}`);
|
|
15293
|
+
this._signatureToName[signature] = placeholder;
|
|
15294
|
+
return placeholder;
|
|
15295
|
+
}
|
|
15296
|
+
getCloseBlockPlaceholderName(name) {
|
|
15297
|
+
const signature = this._hashClosingBlock(name);
|
|
15298
|
+
if (this._signatureToName[signature]) {
|
|
15299
|
+
return this._signatureToName[signature];
|
|
15300
|
+
}
|
|
15301
|
+
const placeholder = this._generateUniqueName(`CLOSE_BLOCK_${this._toSnakeCase(name)}`);
|
|
15302
|
+
this._signatureToName[signature] = placeholder;
|
|
15303
|
+
return placeholder;
|
|
15304
|
+
}
|
|
15140
15305
|
// Generate a hash for a tag - does not take attribute order into account
|
|
15141
15306
|
_hashTag(tag, attrs, isVoid) {
|
|
15142
15307
|
const start = `<${tag}`;
|
|
@@ -15147,6 +15312,16 @@ class PlaceholderRegistry {
|
|
|
15147
15312
|
_hashClosingTag(tag) {
|
|
15148
15313
|
return this._hashTag(`/${tag}`, {}, false);
|
|
15149
15314
|
}
|
|
15315
|
+
_hashBlock(name, parameters) {
|
|
15316
|
+
const params = parameters.length === 0 ? '' : ` (${parameters.sort().join('; ')})`;
|
|
15317
|
+
return `@${name}${params} {}`;
|
|
15318
|
+
}
|
|
15319
|
+
_hashClosingBlock(name) {
|
|
15320
|
+
return this._hashBlock(`close_${name}`, []);
|
|
15321
|
+
}
|
|
15322
|
+
_toSnakeCase(name) {
|
|
15323
|
+
return name.toUpperCase().replace(/[^A-Z0-9]/g, '_');
|
|
15324
|
+
}
|
|
15150
15325
|
_generateUniqueName(base) {
|
|
15151
15326
|
const seen = this._placeHolderNameCounts.hasOwnProperty(base);
|
|
15152
15327
|
if (!seen) {
|
|
@@ -15163,17 +15338,18 @@ const _expParser = new Parser$1(new Lexer());
|
|
|
15163
15338
|
/**
|
|
15164
15339
|
* Returns a function converting html nodes to an i18n Message given an interpolationConfig
|
|
15165
15340
|
*/
|
|
15166
|
-
function createI18nMessageFactory(interpolationConfig) {
|
|
15167
|
-
const visitor = new _I18nVisitor(_expParser, interpolationConfig);
|
|
15341
|
+
function createI18nMessageFactory(interpolationConfig, containerBlocks) {
|
|
15342
|
+
const visitor = new _I18nVisitor(_expParser, interpolationConfig, containerBlocks);
|
|
15168
15343
|
return (nodes, meaning, description, customId, visitNodeFn) => visitor.toI18nMessage(nodes, meaning, description, customId, visitNodeFn);
|
|
15169
15344
|
}
|
|
15170
15345
|
function noopVisitNodeFn(_html, i18n) {
|
|
15171
15346
|
return i18n;
|
|
15172
15347
|
}
|
|
15173
15348
|
class _I18nVisitor {
|
|
15174
|
-
constructor(_expressionParser, _interpolationConfig) {
|
|
15349
|
+
constructor(_expressionParser, _interpolationConfig, _containerBlocks) {
|
|
15175
15350
|
this._expressionParser = _expressionParser;
|
|
15176
15351
|
this._interpolationConfig = _interpolationConfig;
|
|
15352
|
+
this._containerBlocks = _containerBlocks;
|
|
15177
15353
|
}
|
|
15178
15354
|
toI18nMessage(nodes, meaning = '', description = '', customId = '', visitNodeFn) {
|
|
15179
15355
|
const context = {
|
|
@@ -15260,10 +15436,26 @@ class _I18nVisitor {
|
|
|
15260
15436
|
}
|
|
15261
15437
|
visitBlock(block, context) {
|
|
15262
15438
|
const children = visitAll(this, block.children, context);
|
|
15263
|
-
|
|
15439
|
+
if (this._containerBlocks.has(block.name)) {
|
|
15440
|
+
return new Container(children, block.sourceSpan);
|
|
15441
|
+
}
|
|
15442
|
+
const parameters = block.parameters.map(param => param.expression);
|
|
15443
|
+
const startPhName = context.placeholderRegistry.getStartBlockPlaceholderName(block.name, parameters);
|
|
15444
|
+
const closePhName = context.placeholderRegistry.getCloseBlockPlaceholderName(block.name);
|
|
15445
|
+
context.placeholderToContent[startPhName] = {
|
|
15446
|
+
text: block.startSourceSpan.toString(),
|
|
15447
|
+
sourceSpan: block.startSourceSpan,
|
|
15448
|
+
};
|
|
15449
|
+
context.placeholderToContent[closePhName] = {
|
|
15450
|
+
text: block.endSourceSpan ? block.endSourceSpan.toString() : '}',
|
|
15451
|
+
sourceSpan: block.endSourceSpan ?? block.sourceSpan,
|
|
15452
|
+
};
|
|
15453
|
+
const node = new BlockPlaceholder(block.name, parameters, startPhName, closePhName, children, block.sourceSpan, block.startSourceSpan, block.endSourceSpan);
|
|
15264
15454
|
return context.visitNodeFn(block, node);
|
|
15265
15455
|
}
|
|
15266
|
-
visitBlockParameter(_parameter, _context) {
|
|
15456
|
+
visitBlockParameter(_parameter, _context) {
|
|
15457
|
+
throw new Error('Unreachable code');
|
|
15458
|
+
}
|
|
15267
15459
|
/**
|
|
15268
15460
|
* Convert, text and interpolated tokens up into text and placeholder pieces.
|
|
15269
15461
|
*
|
|
@@ -19132,17 +19324,18 @@ const setI18nRefs = (htmlNode, i18nNode) => {
|
|
|
19132
19324
|
* stored with other element's and attribute's information.
|
|
19133
19325
|
*/
|
|
19134
19326
|
class I18nMetaVisitor {
|
|
19135
|
-
constructor(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG, keepI18nAttrs = false, enableI18nLegacyMessageIdFormat = false) {
|
|
19327
|
+
constructor(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG, keepI18nAttrs = false, enableI18nLegacyMessageIdFormat = false, containerBlocks = DEFAULT_CONTAINER_BLOCKS) {
|
|
19136
19328
|
this.interpolationConfig = interpolationConfig;
|
|
19137
19329
|
this.keepI18nAttrs = keepI18nAttrs;
|
|
19138
19330
|
this.enableI18nLegacyMessageIdFormat = enableI18nLegacyMessageIdFormat;
|
|
19331
|
+
this.containerBlocks = containerBlocks;
|
|
19139
19332
|
// whether visited nodes contain i18n information
|
|
19140
19333
|
this.hasI18nMeta = false;
|
|
19141
19334
|
this._errors = [];
|
|
19142
19335
|
}
|
|
19143
19336
|
_generateI18nMessage(nodes, meta = '', visitNodeFn) {
|
|
19144
19337
|
const { meaning, description, customId } = this._parseMetadata(meta);
|
|
19145
|
-
const createI18nMessage = createI18nMessageFactory(this.interpolationConfig);
|
|
19338
|
+
const createI18nMessage = createI18nMessageFactory(this.interpolationConfig, this.containerBlocks);
|
|
19146
19339
|
const message = createI18nMessage(nodes, meaning, description, customId, visitNodeFn);
|
|
19147
19340
|
this._setMessageId(message, meta);
|
|
19148
19341
|
this._setLegacyIds(message, meta);
|
|
@@ -19443,6 +19636,9 @@ class GetMsgSerializerVisitor {
|
|
|
19443
19636
|
visitPlaceholder(ph) {
|
|
19444
19637
|
return this.formatPh(ph.name);
|
|
19445
19638
|
}
|
|
19639
|
+
visitBlockPlaceholder(ph) {
|
|
19640
|
+
return `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`;
|
|
19641
|
+
}
|
|
19446
19642
|
visitIcuPlaceholder(ph, context) {
|
|
19447
19643
|
return this.formatPh(ph.name);
|
|
19448
19644
|
}
|
|
@@ -19496,6 +19692,11 @@ class LocalizeSerializerVisitor {
|
|
|
19496
19692
|
visitPlaceholder(ph) {
|
|
19497
19693
|
this.pieces.push(this.createPlaceholderPiece(ph.name, ph.sourceSpan));
|
|
19498
19694
|
}
|
|
19695
|
+
visitBlockPlaceholder(ph) {
|
|
19696
|
+
this.pieces.push(this.createPlaceholderPiece(ph.startName, ph.startSourceSpan ?? ph.sourceSpan));
|
|
19697
|
+
ph.children.forEach(child => child.visit(this));
|
|
19698
|
+
this.pieces.push(this.createPlaceholderPiece(ph.closeName, ph.endSourceSpan ?? ph.sourceSpan));
|
|
19699
|
+
}
|
|
19499
19700
|
visitIcuPlaceholder(ph) {
|
|
19500
19701
|
this.pieces.push(this.createPlaceholderPiece(ph.name, ph.sourceSpan, this.placeholderToMessage[ph.name]));
|
|
19501
19702
|
}
|
|
@@ -19826,57 +20027,6 @@ function serializeLocalRefs(refs) {
|
|
|
19826
20027
|
return literalArr(constRefs);
|
|
19827
20028
|
}
|
|
19828
20029
|
|
|
19829
|
-
/**
|
|
19830
|
-
* Merge i18n contexts for child i18n blocks into their ancestor root contexts.
|
|
19831
|
-
*/
|
|
19832
|
-
function mergeI18nContexts(job) {
|
|
19833
|
-
// Record all of the i18n and extracted message ops for use later.
|
|
19834
|
-
const i18nOps = new Map();
|
|
19835
|
-
const i18nContexts = new Map();
|
|
19836
|
-
for (const unit of job.units) {
|
|
19837
|
-
for (const op of unit.create) {
|
|
19838
|
-
switch (op.kind) {
|
|
19839
|
-
case OpKind.I18nStart:
|
|
19840
|
-
if (!op.context) {
|
|
19841
|
-
throw Error('I18n op should have its context set.');
|
|
19842
|
-
}
|
|
19843
|
-
i18nOps.set(op.xref, op);
|
|
19844
|
-
break;
|
|
19845
|
-
case OpKind.I18nContext:
|
|
19846
|
-
i18nContexts.set(op.xref, op);
|
|
19847
|
-
break;
|
|
19848
|
-
}
|
|
19849
|
-
}
|
|
19850
|
-
}
|
|
19851
|
-
// For each non-root i18n op, merge its context into the root i18n op's context.
|
|
19852
|
-
for (const childI18nOp of i18nOps.values()) {
|
|
19853
|
-
if (childI18nOp.xref !== childI18nOp.root) {
|
|
19854
|
-
const childContext = i18nContexts.get(childI18nOp.context);
|
|
19855
|
-
const rootI18nOp = i18nOps.get(childI18nOp.root);
|
|
19856
|
-
const rootContext = i18nContexts.get(rootI18nOp.context);
|
|
19857
|
-
mergeParams(rootContext.params, childContext.params);
|
|
19858
|
-
mergeParams(rootContext.postprocessingParams, childContext.postprocessingParams);
|
|
19859
|
-
}
|
|
19860
|
-
}
|
|
19861
|
-
}
|
|
19862
|
-
/**
|
|
19863
|
-
* Merges the params in the `from` map to into the `to` map.
|
|
19864
|
-
*/
|
|
19865
|
-
function mergeParams(to, from) {
|
|
19866
|
-
for (const [placeholder, fromValues] of from) {
|
|
19867
|
-
const toValues = to.get(placeholder) || [];
|
|
19868
|
-
// TODO(mmalerba): Child element close tag params should be prepended to maintain the same order
|
|
19869
|
-
// as TemplateDefinitionBuilder. Can be cleaned up when compatibility is no longer required.
|
|
19870
|
-
const flags = fromValues[0].flags;
|
|
19871
|
-
if ((flags & I18nParamValueFlags.CloseTag) && !(flags & I18nParamValueFlags.OpenTag)) {
|
|
19872
|
-
to.set(placeholder, [...fromValues, ...toValues]);
|
|
19873
|
-
}
|
|
19874
|
-
else {
|
|
19875
|
-
to.set(placeholder, [...toValues, ...fromValues]);
|
|
19876
|
-
}
|
|
19877
|
-
}
|
|
19878
|
-
}
|
|
19879
|
-
|
|
19880
20030
|
/**
|
|
19881
20031
|
* Change namespaces between HTML, SVG and MathML, depending on the next element.
|
|
19882
20032
|
*/
|
|
@@ -20540,9 +20690,10 @@ function propagateI18nBlocksToTemplates(unit, subTemplateIndex) {
|
|
|
20540
20690
|
wrapTemplateWithI18n(templateView, i18nBlock);
|
|
20541
20691
|
}
|
|
20542
20692
|
// Continue traversing inside the template's view.
|
|
20543
|
-
propagateI18nBlocksToTemplates(templateView, subTemplateIndex);
|
|
20693
|
+
subTemplateIndex = propagateI18nBlocksToTemplates(templateView, subTemplateIndex);
|
|
20544
20694
|
}
|
|
20545
20695
|
}
|
|
20696
|
+
return subTemplateIndex;
|
|
20546
20697
|
}
|
|
20547
20698
|
/**
|
|
20548
20699
|
* Wraps a template view with i18n start and end ops.
|
|
@@ -20850,8 +21001,8 @@ function repeaterCreate(slot, viewFnName, decls, vars, tag, constIndex, trackByF
|
|
|
20850
21001
|
}
|
|
20851
21002
|
return call(Identifiers.repeaterCreate, args, sourceSpan);
|
|
20852
21003
|
}
|
|
20853
|
-
function repeater(
|
|
20854
|
-
return call(Identifiers.repeater, [
|
|
21004
|
+
function repeater(collection, sourceSpan) {
|
|
21005
|
+
return call(Identifiers.repeater, [collection], sourceSpan);
|
|
20855
21006
|
}
|
|
20856
21007
|
function deferWhen(prefetch, expr, sourceSpan) {
|
|
20857
21008
|
return call(prefetch ? Identifiers.deferPrefetchWhen : Identifiers.deferWhen, [expr], sourceSpan);
|
|
@@ -21459,7 +21610,7 @@ function reifyUpdateOperations(_unit, ops) {
|
|
|
21459
21610
|
OpList.replace(op, conditional(op.targetSlot.slot, op.processed, op.contextValue, op.sourceSpan));
|
|
21460
21611
|
break;
|
|
21461
21612
|
case OpKind.Repeater:
|
|
21462
|
-
OpList.replace(op, repeater(op.
|
|
21613
|
+
OpList.replace(op, repeater(op.collection, op.sourceSpan));
|
|
21463
21614
|
break;
|
|
21464
21615
|
case OpKind.DeferWhen:
|
|
21465
21616
|
OpList.replace(op, deferWhen(op.prefetch, op.expr, op.sourceSpan));
|
|
@@ -21722,66 +21873,79 @@ function resolveI18nElementPlaceholders(job) {
|
|
|
21722
21873
|
}
|
|
21723
21874
|
}
|
|
21724
21875
|
}
|
|
21725
|
-
|
|
21726
|
-
|
|
21727
|
-
|
|
21728
|
-
|
|
21729
|
-
|
|
21730
|
-
|
|
21731
|
-
|
|
21732
|
-
|
|
21733
|
-
|
|
21876
|
+
resolvePlaceholdersForView(job, job.root, i18nContexts, elements);
|
|
21877
|
+
}
|
|
21878
|
+
function resolvePlaceholdersForView(job, unit, i18nContexts, elements) {
|
|
21879
|
+
// Track the current i18n op and corresponding i18n context op as we step through the creation
|
|
21880
|
+
// IR.
|
|
21881
|
+
let currentOps = null;
|
|
21882
|
+
for (const op of unit.create) {
|
|
21883
|
+
switch (op.kind) {
|
|
21884
|
+
case OpKind.I18nStart:
|
|
21885
|
+
if (!op.context) {
|
|
21886
|
+
throw Error('Could not find i18n context for i18n op');
|
|
21887
|
+
}
|
|
21888
|
+
currentOps = { i18nBlock: op, i18nContext: i18nContexts.get(op.context) };
|
|
21889
|
+
break;
|
|
21890
|
+
case OpKind.I18nEnd:
|
|
21891
|
+
currentOps = null;
|
|
21892
|
+
break;
|
|
21893
|
+
case OpKind.ElementStart:
|
|
21894
|
+
// For elements with i18n placeholders, record its slot value in the params map under the
|
|
21895
|
+
// corresponding tag start placeholder.
|
|
21896
|
+
if (op.i18nPlaceholder !== undefined) {
|
|
21897
|
+
if (currentOps === null) {
|
|
21898
|
+
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
21734
21899
|
}
|
|
21735
|
-
|
|
21736
|
-
|
|
21737
|
-
|
|
21738
|
-
|
|
21739
|
-
|
|
21740
|
-
|
|
21741
|
-
// For elements with i18n placeholders, record its slot value in the params map under the
|
|
21742
|
-
// corresponding tag start placeholder.
|
|
21743
|
-
if (op.i18nPlaceholder !== undefined) {
|
|
21744
|
-
if (currentOps === null) {
|
|
21745
|
-
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
21746
|
-
}
|
|
21747
|
-
const { startName, closeName } = op.i18nPlaceholder;
|
|
21748
|
-
let flags = I18nParamValueFlags.ElementTag | I18nParamValueFlags.OpenTag;
|
|
21749
|
-
// For self-closing tags, there is no close tag placeholder. Instead, the start tag
|
|
21750
|
-
// placeholder accounts for the start and close of the element.
|
|
21751
|
-
if (closeName === '') {
|
|
21752
|
-
flags |= I18nParamValueFlags.CloseTag;
|
|
21753
|
-
}
|
|
21754
|
-
addParam(currentOps.i18nContext.params, startName, op.handle.slot, currentOps.i18nBlock.subTemplateIndex, flags);
|
|
21900
|
+
const { startName, closeName } = op.i18nPlaceholder;
|
|
21901
|
+
let flags = I18nParamValueFlags.ElementTag | I18nParamValueFlags.OpenTag;
|
|
21902
|
+
// For self-closing tags, there is no close tag placeholder. Instead, the start tag
|
|
21903
|
+
// placeholder accounts for the start and close of the element.
|
|
21904
|
+
if (closeName === '') {
|
|
21905
|
+
flags |= I18nParamValueFlags.CloseTag;
|
|
21755
21906
|
}
|
|
21756
|
-
|
|
21757
|
-
|
|
21758
|
-
|
|
21759
|
-
|
|
21760
|
-
|
|
21761
|
-
|
|
21762
|
-
|
|
21763
|
-
|
|
21764
|
-
|
|
21765
|
-
|
|
21766
|
-
// Self-closing tags don't have a closing tag placeholder.
|
|
21767
|
-
if (closeName !== '') {
|
|
21768
|
-
addParam(currentOps.i18nContext.params, closeName, startOp.handle.slot, currentOps.i18nBlock.subTemplateIndex, I18nParamValueFlags.ElementTag | I18nParamValueFlags.CloseTag);
|
|
21769
|
-
}
|
|
21907
|
+
addParam(currentOps.i18nContext.params, startName, op.handle.slot, currentOps.i18nBlock.subTemplateIndex, flags);
|
|
21908
|
+
}
|
|
21909
|
+
break;
|
|
21910
|
+
case OpKind.ElementEnd:
|
|
21911
|
+
// For elements with i18n placeholders, record its slot value in the params map under the
|
|
21912
|
+
// corresponding tag close placeholder.
|
|
21913
|
+
const startOp = elements.get(op.xref);
|
|
21914
|
+
if (startOp && startOp.i18nPlaceholder !== undefined) {
|
|
21915
|
+
if (currentOps === null) {
|
|
21916
|
+
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
21770
21917
|
}
|
|
21771
|
-
|
|
21772
|
-
|
|
21773
|
-
|
|
21774
|
-
|
|
21775
|
-
if (op.i18nPlaceholder !== undefined) {
|
|
21776
|
-
if (currentOps === null) {
|
|
21777
|
-
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
21778
|
-
}
|
|
21779
|
-
const subTemplateIndex = getSubTemplateIndexForTemplateTag(job, currentOps.i18nBlock, op);
|
|
21780
|
-
addParam(currentOps.i18nContext.params, op.i18nPlaceholder.startName, op.handle.slot, subTemplateIndex, I18nParamValueFlags.TemplateTag);
|
|
21781
|
-
addParam(currentOps.i18nContext.params, op.i18nPlaceholder.closeName, op.handle.slot, subTemplateIndex, I18nParamValueFlags.TemplateTag | I18nParamValueFlags.CloseTag);
|
|
21918
|
+
const { closeName } = startOp.i18nPlaceholder;
|
|
21919
|
+
// Self-closing tags don't have a closing tag placeholder.
|
|
21920
|
+
if (closeName !== '') {
|
|
21921
|
+
addParam(currentOps.i18nContext.params, closeName, startOp.handle.slot, currentOps.i18nBlock.subTemplateIndex, I18nParamValueFlags.ElementTag | I18nParamValueFlags.CloseTag);
|
|
21782
21922
|
}
|
|
21783
|
-
|
|
21784
|
-
|
|
21923
|
+
}
|
|
21924
|
+
break;
|
|
21925
|
+
case OpKind.Template:
|
|
21926
|
+
// For templates with i18n placeholders, record its slot value in the params map under the
|
|
21927
|
+
// corresponding template start and close placeholders.
|
|
21928
|
+
if (op.i18nPlaceholder !== undefined) {
|
|
21929
|
+
if (currentOps === null) {
|
|
21930
|
+
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
21931
|
+
}
|
|
21932
|
+
let startFlags = I18nParamValueFlags.TemplateTag | I18nParamValueFlags.OpenTag;
|
|
21933
|
+
const subTemplateIndex = getSubTemplateIndexForTemplateTag(job, currentOps.i18nBlock, op);
|
|
21934
|
+
const { startName, closeName } = op.i18nPlaceholder;
|
|
21935
|
+
const isSelfClosing = closeName === '';
|
|
21936
|
+
if (isSelfClosing) {
|
|
21937
|
+
startFlags |= I18nParamValueFlags.CloseTag;
|
|
21938
|
+
}
|
|
21939
|
+
addParam(currentOps.i18nContext.params, startName, op.handle.slot, subTemplateIndex, startFlags);
|
|
21940
|
+
resolvePlaceholdersForView(job, job.views.get(op.xref), i18nContexts, elements);
|
|
21941
|
+
if (!isSelfClosing) {
|
|
21942
|
+
addParam(currentOps.i18nContext.params, closeName, op.handle.slot, subTemplateIndex, I18nParamValueFlags.TemplateTag | I18nParamValueFlags.CloseTag);
|
|
21943
|
+
}
|
|
21944
|
+
}
|
|
21945
|
+
else {
|
|
21946
|
+
resolvePlaceholdersForView(job, job.views.get(op.xref), i18nContexts, elements);
|
|
21947
|
+
}
|
|
21948
|
+
break;
|
|
21785
21949
|
}
|
|
21786
21950
|
}
|
|
21787
21951
|
}
|
|
@@ -21829,8 +21993,8 @@ function resolveI18nExpressionPlaceholders(job) {
|
|
|
21829
21993
|
for (const op of unit.update) {
|
|
21830
21994
|
if (op.kind === OpKind.I18nExpression) {
|
|
21831
21995
|
const i18nContext = i18nContexts.get(op.context);
|
|
21832
|
-
const index = expressionIndices.get(
|
|
21833
|
-
const subTemplateIndex = subTemplateIndicies.get(
|
|
21996
|
+
const index = expressionIndices.get(op.target) || 0;
|
|
21997
|
+
const subTemplateIndex = subTemplateIndicies.get(op.target);
|
|
21834
21998
|
// Add the expression index in the appropriate params map.
|
|
21835
21999
|
const params = op.resolutionTime === I18nParamResolutionTime.Creation ?
|
|
21836
22000
|
i18nContext.params :
|
|
@@ -21842,7 +22006,7 @@ function resolveI18nExpressionPlaceholders(job) {
|
|
|
21842
22006
|
flags: I18nParamValueFlags.ExpressionIndex
|
|
21843
22007
|
});
|
|
21844
22008
|
params.set(op.i18nPlaceholder, values);
|
|
21845
|
-
expressionIndices.set(
|
|
22009
|
+
expressionIndices.set(op.target, index + 1);
|
|
21846
22010
|
}
|
|
21847
22011
|
}
|
|
21848
22012
|
}
|
|
@@ -21852,28 +22016,12 @@ function resolveI18nExpressionPlaceholders(job) {
|
|
|
21852
22016
|
* Resolves placeholders for element tags inside of an ICU.
|
|
21853
22017
|
*/
|
|
21854
22018
|
function resolveI18nIcuPlaceholders(job) {
|
|
21855
|
-
const contextOps = new Map();
|
|
21856
|
-
for (const unit of job.units) {
|
|
21857
|
-
for (const op of unit.create) {
|
|
21858
|
-
switch (op.kind) {
|
|
21859
|
-
case OpKind.I18nContext:
|
|
21860
|
-
contextOps.set(op.xref, op);
|
|
21861
|
-
break;
|
|
21862
|
-
}
|
|
21863
|
-
}
|
|
21864
|
-
}
|
|
21865
22019
|
for (const unit of job.units) {
|
|
21866
22020
|
for (const op of unit.create) {
|
|
21867
|
-
|
|
21868
|
-
|
|
21869
|
-
|
|
21870
|
-
|
|
21871
|
-
}
|
|
21872
|
-
const i18nContext = contextOps.get(op.context);
|
|
21873
|
-
for (const node of op.message.nodes) {
|
|
21874
|
-
node.visit(new ResolveIcuPlaceholdersVisitor(i18nContext.postprocessingParams));
|
|
21875
|
-
}
|
|
21876
|
-
break;
|
|
22021
|
+
if (op.kind === OpKind.I18nContext && op.contextKind === I18nContextKind.Icu) {
|
|
22022
|
+
for (const node of op.message.nodes) {
|
|
22023
|
+
node.visit(new ResolveIcuPlaceholdersVisitor(op.postprocessingParams));
|
|
22024
|
+
}
|
|
21877
22025
|
}
|
|
21878
22026
|
}
|
|
21879
22027
|
}
|
|
@@ -21886,10 +22034,9 @@ class ResolveIcuPlaceholdersVisitor extends RecurseVisitor {
|
|
|
21886
22034
|
super();
|
|
21887
22035
|
this.params = params;
|
|
21888
22036
|
}
|
|
21889
|
-
|
|
21890
|
-
|
|
21891
|
-
//
|
|
21892
|
-
// elements inside ICUs. The slots for the elements were recorded separately under the i18n
|
|
22037
|
+
visitContainerPlaceholder(placeholder) {
|
|
22038
|
+
// Add the start and end source span for container placeholders. These need to be recorded for
|
|
22039
|
+
// elements inside ICUs. The slots for the nodes were recorded separately under the i18n
|
|
21893
22040
|
// block's context as part of the `resolveI18nElementPlaceholders` phase.
|
|
21894
22041
|
if (placeholder.startName && placeholder.startSourceSpan &&
|
|
21895
22042
|
!this.params.has(placeholder.startName)) {
|
|
@@ -21908,6 +22055,14 @@ class ResolveIcuPlaceholdersVisitor extends RecurseVisitor {
|
|
|
21908
22055
|
}]);
|
|
21909
22056
|
}
|
|
21910
22057
|
}
|
|
22058
|
+
visitTagPlaceholder(placeholder) {
|
|
22059
|
+
super.visitTagPlaceholder(placeholder);
|
|
22060
|
+
this.visitContainerPlaceholder(placeholder);
|
|
22061
|
+
}
|
|
22062
|
+
visitBlockPlaceholder(placeholder) {
|
|
22063
|
+
super.visitBlockPlaceholder(placeholder);
|
|
22064
|
+
this.visitContainerPlaceholder(placeholder);
|
|
22065
|
+
}
|
|
21911
22066
|
}
|
|
21912
22067
|
|
|
21913
22068
|
/**
|
|
@@ -23036,7 +23191,6 @@ const phases = [
|
|
|
23036
23191
|
{ kind: CompilationJobKind.Tmpl, fn: resolveI18nElementPlaceholders },
|
|
23037
23192
|
{ kind: CompilationJobKind.Tmpl, fn: resolveI18nExpressionPlaceholders },
|
|
23038
23193
|
{ kind: CompilationJobKind.Tmpl, fn: resolveI18nIcuPlaceholders },
|
|
23039
|
-
{ kind: CompilationJobKind.Tmpl, fn: mergeI18nContexts },
|
|
23040
23194
|
{ kind: CompilationJobKind.Tmpl, fn: extractI18nMessages },
|
|
23041
23195
|
{ kind: CompilationJobKind.Tmpl, fn: generateTrackFns },
|
|
23042
23196
|
{ kind: CompilationJobKind.Tmpl, fn: collectI18nConsts },
|
|
@@ -25102,19 +25256,19 @@ function createIfBlock(ast, connectedBlocks, visitor, bindingParser) {
|
|
|
25102
25256
|
const branches = [];
|
|
25103
25257
|
const mainBlockParams = parseConditionalBlockParameters(ast, errors, bindingParser);
|
|
25104
25258
|
if (mainBlockParams !== null) {
|
|
25105
|
-
branches.push(new IfBlockBranch(mainBlockParams.expression, visitAll(visitor, ast.children, ast.children), mainBlockParams.expressionAlias, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.nameSpan));
|
|
25259
|
+
branches.push(new IfBlockBranch(mainBlockParams.expression, visitAll(visitor, ast.children, ast.children), mainBlockParams.expressionAlias, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.nameSpan, ast.i18n));
|
|
25106
25260
|
}
|
|
25107
25261
|
for (const block of connectedBlocks) {
|
|
25108
25262
|
if (ELSE_IF_PATTERN.test(block.name)) {
|
|
25109
25263
|
const params = parseConditionalBlockParameters(block, errors, bindingParser);
|
|
25110
25264
|
if (params !== null) {
|
|
25111
25265
|
const children = visitAll(visitor, block.children, block.children);
|
|
25112
|
-
branches.push(new IfBlockBranch(params.expression, children, params.expressionAlias, block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan));
|
|
25266
|
+
branches.push(new IfBlockBranch(params.expression, children, params.expressionAlias, block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan, block.i18n));
|
|
25113
25267
|
}
|
|
25114
25268
|
}
|
|
25115
25269
|
else if (block.name === 'else') {
|
|
25116
25270
|
const children = visitAll(visitor, block.children, block.children);
|
|
25117
|
-
branches.push(new IfBlockBranch(null, children, null, block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan));
|
|
25271
|
+
branches.push(new IfBlockBranch(null, children, null, block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan, block.i18n));
|
|
25118
25272
|
}
|
|
25119
25273
|
}
|
|
25120
25274
|
// The outer IfBlock should have a span that encapsulates all branches.
|
|
@@ -25145,7 +25299,7 @@ function createForLoop(ast, connectedBlocks, visitor, bindingParser) {
|
|
|
25145
25299
|
errors.push(new ParseError(block.sourceSpan, '@empty block cannot have parameters'));
|
|
25146
25300
|
}
|
|
25147
25301
|
else {
|
|
25148
|
-
empty = new ForLoopBlockEmpty(visitAll(visitor, block.children, block.children), block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan);
|
|
25302
|
+
empty = new ForLoopBlockEmpty(visitAll(visitor, block.children, block.children), block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan, block.i18n);
|
|
25149
25303
|
}
|
|
25150
25304
|
}
|
|
25151
25305
|
else {
|
|
@@ -25163,7 +25317,7 @@ function createForLoop(ast, connectedBlocks, visitor, bindingParser) {
|
|
|
25163
25317
|
// main `for` body, use `mainSourceSpan`.
|
|
25164
25318
|
const endSpan = empty?.endSourceSpan ?? ast.endSourceSpan;
|
|
25165
25319
|
const sourceSpan = new ParseSourceSpan(ast.sourceSpan.start, endSpan?.end ?? ast.sourceSpan.end);
|
|
25166
|
-
node = new ForLoopBlock(params.itemName, params.expression, params.trackBy.expression, params.trackBy.keywordSpan, params.context, visitAll(visitor, ast.children, ast.children), empty, sourceSpan, ast.sourceSpan, ast.startSourceSpan, endSpan, ast.nameSpan);
|
|
25320
|
+
node = new ForLoopBlock(params.itemName, params.expression, params.trackBy.expression, params.trackBy.keywordSpan, params.context, visitAll(visitor, ast.children, ast.children), empty, sourceSpan, ast.sourceSpan, ast.startSourceSpan, endSpan, ast.nameSpan, ast.i18n);
|
|
25167
25321
|
}
|
|
25168
25322
|
}
|
|
25169
25323
|
return { node, errors };
|
|
@@ -25189,7 +25343,7 @@ function createSwitchBlock(ast, visitor, bindingParser) {
|
|
|
25189
25343
|
const expression = node.name === 'case' ?
|
|
25190
25344
|
parseBlockParameterToBinding(node.parameters[0], bindingParser) :
|
|
25191
25345
|
null;
|
|
25192
|
-
const ast = new SwitchBlockCase(expression, visitAll(visitor, node.children, node.children), node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.nameSpan);
|
|
25346
|
+
const ast = new SwitchBlockCase(expression, visitAll(visitor, node.children, node.children), node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.nameSpan, node.i18n);
|
|
25193
25347
|
if (expression === null) {
|
|
25194
25348
|
defaultCase = ast;
|
|
25195
25349
|
}
|
|
@@ -25776,7 +25930,7 @@ function createDeferredBlock(ast, connectedBlocks, visitor, bindingParser) {
|
|
|
25776
25930
|
endOfLastSourceSpan = lastConnectedBlock.sourceSpan.end;
|
|
25777
25931
|
}
|
|
25778
25932
|
const sourceSpanWithConnectedBlocks = new ParseSourceSpan(ast.sourceSpan.start, endOfLastSourceSpan);
|
|
25779
|
-
const node = new DeferredBlock(visitAll(visitor, ast.children, ast.children), triggers, prefetchTriggers, placeholder, loading, error, ast.nameSpan, sourceSpanWithConnectedBlocks, ast.sourceSpan, ast.startSourceSpan, lastEndSourceSpan);
|
|
25933
|
+
const node = new DeferredBlock(visitAll(visitor, ast.children, ast.children), triggers, prefetchTriggers, placeholder, loading, error, ast.nameSpan, sourceSpanWithConnectedBlocks, ast.sourceSpan, ast.startSourceSpan, lastEndSourceSpan, ast.i18n);
|
|
25780
25934
|
return { node, errors };
|
|
25781
25935
|
}
|
|
25782
25936
|
function parseConnectedBlocks(connectedBlocks, errors, visitor) {
|
|
@@ -25839,7 +25993,7 @@ function parsePlaceholderBlock(ast, visitor) {
|
|
|
25839
25993
|
throw new Error(`Unrecognized parameter in @placeholder block: "${param.expression}"`);
|
|
25840
25994
|
}
|
|
25841
25995
|
}
|
|
25842
|
-
return new DeferredBlockPlaceholder(visitAll(visitor, ast.children, ast.children), minimumTime, ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
25996
|
+
return new DeferredBlockPlaceholder(visitAll(visitor, ast.children, ast.children), minimumTime, ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.i18n);
|
|
25843
25997
|
}
|
|
25844
25998
|
function parseLoadingBlock(ast, visitor) {
|
|
25845
25999
|
let afterTime = null;
|
|
@@ -25869,13 +26023,13 @@ function parseLoadingBlock(ast, visitor) {
|
|
|
25869
26023
|
throw new Error(`Unrecognized parameter in @loading block: "${param.expression}"`);
|
|
25870
26024
|
}
|
|
25871
26025
|
}
|
|
25872
|
-
return new DeferredBlockLoading(visitAll(visitor, ast.children, ast.children), afterTime, minimumTime, ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
26026
|
+
return new DeferredBlockLoading(visitAll(visitor, ast.children, ast.children), afterTime, minimumTime, ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.i18n);
|
|
25873
26027
|
}
|
|
25874
26028
|
function parseErrorBlock(ast, visitor) {
|
|
25875
26029
|
if (ast.parameters.length > 0) {
|
|
25876
26030
|
throw new Error(`@error block cannot have parameters`);
|
|
25877
26031
|
}
|
|
25878
|
-
return new DeferredBlockError(visitAll(visitor, ast.children, ast.children), ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
26032
|
+
return new DeferredBlockError(visitAll(visitor, ast.children, ast.children), ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.i18n);
|
|
25879
26033
|
}
|
|
25880
26034
|
function parsePrimaryTriggers(params, bindingParser, errors, placeholder) {
|
|
25881
26035
|
const triggers = {};
|
|
@@ -26475,6 +26629,11 @@ class I18nContext {
|
|
|
26475
26629
|
const content = { type, index, ctx: this.id, isVoid: node.isVoid, closed };
|
|
26476
26630
|
updatePlaceholderMap(this.placeholders, ph, content);
|
|
26477
26631
|
}
|
|
26632
|
+
appendBlockPart(node, index, closed) {
|
|
26633
|
+
const ph = closed ? node.closeName : node.startName;
|
|
26634
|
+
const content = { type: TagType.TEMPLATE, index, ctx: this.id, closed };
|
|
26635
|
+
updatePlaceholderMap(this.placeholders, ph, content);
|
|
26636
|
+
}
|
|
26478
26637
|
get icus() {
|
|
26479
26638
|
return this._registry.icus;
|
|
26480
26639
|
}
|
|
@@ -26507,6 +26666,13 @@ class I18nContext {
|
|
|
26507
26666
|
this.appendTag(TagType.TEMPLATE, node, index, true);
|
|
26508
26667
|
this._unresolvedCtxCount++;
|
|
26509
26668
|
}
|
|
26669
|
+
appendBlock(node, index) {
|
|
26670
|
+
// add open and close tags at the same time,
|
|
26671
|
+
// since we process nested templates separately
|
|
26672
|
+
this.appendBlockPart(node, index, false);
|
|
26673
|
+
this.appendBlockPart(node, index, true);
|
|
26674
|
+
this._unresolvedCtxCount++;
|
|
26675
|
+
}
|
|
26510
26676
|
appendElement(node, index, closed) {
|
|
26511
26677
|
this.appendTag(TagType.ELEMENT, node, index, closed);
|
|
26512
26678
|
}
|
|
@@ -26785,13 +26951,19 @@ class TemplateDefinitionBuilder {
|
|
|
26785
26951
|
this.creationInstruction(null, Identifiers.pipe, [literal(slot), literal(name)]);
|
|
26786
26952
|
});
|
|
26787
26953
|
}
|
|
26788
|
-
buildTemplateFunction(nodes, variables, ngContentSelectorsOffset = 0, i18n) {
|
|
26954
|
+
buildTemplateFunction(nodes, variables, ngContentSelectorsOffset = 0, i18n, variableAliases) {
|
|
26789
26955
|
this._ngContentSelectorsOffset = ngContentSelectorsOffset;
|
|
26790
26956
|
if (this._namespace !== Identifiers.namespaceHTML) {
|
|
26791
26957
|
this.creationInstruction(null, this._namespace);
|
|
26792
26958
|
}
|
|
26793
26959
|
// Create variable bindings
|
|
26794
|
-
variables.forEach(v =>
|
|
26960
|
+
variables.forEach(v => {
|
|
26961
|
+
const alias = variableAliases?.[v.name];
|
|
26962
|
+
this.registerContextVariables(v.name, v.value);
|
|
26963
|
+
if (alias) {
|
|
26964
|
+
this.registerContextVariables(alias, v.value);
|
|
26965
|
+
}
|
|
26966
|
+
});
|
|
26795
26967
|
// Initiate i18n context in case:
|
|
26796
26968
|
// - this template has parent i18n context
|
|
26797
26969
|
// - or the template has i18n meta associated with it,
|
|
@@ -26885,12 +27057,12 @@ class TemplateDefinitionBuilder {
|
|
|
26885
27057
|
this._constants.prepareStatements.push(...statements);
|
|
26886
27058
|
return _ref;
|
|
26887
27059
|
}
|
|
26888
|
-
registerContextVariables(
|
|
27060
|
+
registerContextVariables(name, value) {
|
|
26889
27061
|
const scopedName = this._bindingScope.freshReferenceName();
|
|
26890
27062
|
const retrievalLevel = this.level;
|
|
26891
|
-
const isDirect =
|
|
26892
|
-
const lhs = variable(
|
|
26893
|
-
this._bindingScope.set(retrievalLevel,
|
|
27063
|
+
const isDirect = value === DIRECT_CONTEXT_REFERENCE;
|
|
27064
|
+
const lhs = variable(name + scopedName);
|
|
27065
|
+
this._bindingScope.set(retrievalLevel, name, scope => {
|
|
26894
27066
|
// If we're at the top level and we're referring to the context variable directly, we
|
|
26895
27067
|
// can do so through the implicit receiver, instead of renaming it. Note that this does
|
|
26896
27068
|
// not apply to listeners, because they need to restore the context.
|
|
@@ -26926,7 +27098,7 @@ class TemplateDefinitionBuilder {
|
|
|
26926
27098
|
return [
|
|
26927
27099
|
// e.g. const $items$ = x(2) for direct context references and
|
|
26928
27100
|
// const $item$ = x(2).$implicit for indirect ones.
|
|
26929
|
-
lhs.set(isDirect ? rhs : rhs.prop(
|
|
27101
|
+
lhs.set(isDirect ? rhs : rhs.prop(value || IMPLICIT_REFERENCE)).toConstDecl()
|
|
26930
27102
|
];
|
|
26931
27103
|
});
|
|
26932
27104
|
}
|
|
@@ -27349,10 +27521,15 @@ class TemplateDefinitionBuilder {
|
|
|
27349
27521
|
this.creationInstruction(span, isNgContainer$1 ? Identifiers.elementContainerEnd : Identifiers.elementEnd);
|
|
27350
27522
|
}
|
|
27351
27523
|
}
|
|
27352
|
-
prepareEmbeddedTemplateFn(children, contextNameSuffix, variables = [],
|
|
27524
|
+
prepareEmbeddedTemplateFn(children, contextNameSuffix, variables = [], i18nMeta, variableAliases) {
|
|
27353
27525
|
const index = this.allocateDataSlot();
|
|
27354
|
-
if (this.i18n &&
|
|
27355
|
-
|
|
27526
|
+
if (this.i18n && i18nMeta) {
|
|
27527
|
+
if (i18nMeta instanceof BlockPlaceholder) {
|
|
27528
|
+
this.i18n.appendBlock(i18nMeta, index);
|
|
27529
|
+
}
|
|
27530
|
+
else {
|
|
27531
|
+
this.i18n.appendTemplate(i18nMeta, index);
|
|
27532
|
+
}
|
|
27356
27533
|
}
|
|
27357
27534
|
const contextName = `${this.contextName}${contextNameSuffix}_${index}`;
|
|
27358
27535
|
const name = `${contextName}_Template`;
|
|
@@ -27363,7 +27540,7 @@ class TemplateDefinitionBuilder {
|
|
|
27363
27540
|
// be able to support bindings in nested templates to local refs that occur after the
|
|
27364
27541
|
// template definition. e.g. <div *ngIf="showing">{{ foo }}</div> <div #foo></div>
|
|
27365
27542
|
this._nestedTemplateFns.push(() => {
|
|
27366
|
-
const templateFunctionExpr = visitor.buildTemplateFunction(children, variables, this._ngContentReservedSlots.length + this._ngContentSelectorsOffset,
|
|
27543
|
+
const templateFunctionExpr = visitor.buildTemplateFunction(children, variables, this._ngContentReservedSlots.length + this._ngContentSelectorsOffset, i18nMeta, variableAliases);
|
|
27367
27544
|
this.constantPool.statements.push(templateFunctionExpr.toDeclStmt(name));
|
|
27368
27545
|
if (visitor._ngContentReservedSlots.length) {
|
|
27369
27546
|
this._ngContentReservedSlots.push(...visitor._ngContentReservedSlots);
|
|
@@ -27520,7 +27697,7 @@ class TemplateDefinitionBuilder {
|
|
|
27520
27697
|
}
|
|
27521
27698
|
// Note: the template needs to be created *before* we process the expression,
|
|
27522
27699
|
// otherwise pipes injecting some symbols won't work (see #52102).
|
|
27523
|
-
const templateIndex = this.createEmbeddedTemplateFn(tagName, children, '_Conditional', sourceSpan, variables, attrsExprs);
|
|
27700
|
+
const templateIndex = this.createEmbeddedTemplateFn(tagName, children, '_Conditional', sourceSpan, variables, attrsExprs, undefined, branch.i18n);
|
|
27524
27701
|
const processedExpression = expression === null ? null : expression.visit(this._valueConverter);
|
|
27525
27702
|
return { index: templateIndex, expression: processedExpression, alias: expressionAlias };
|
|
27526
27703
|
});
|
|
@@ -27571,7 +27748,7 @@ class TemplateDefinitionBuilder {
|
|
|
27571
27748
|
// We have to process the block in two steps: once here and again in the update instruction
|
|
27572
27749
|
// callback in order to generate the correct expressions when pipes or pure functions are used.
|
|
27573
27750
|
const caseData = block.cases.map(currentCase => {
|
|
27574
|
-
const index = this.createEmbeddedTemplateFn(null, currentCase.children, '_Case', currentCase.sourceSpan);
|
|
27751
|
+
const index = this.createEmbeddedTemplateFn(null, currentCase.children, '_Case', currentCase.sourceSpan, undefined, undefined, undefined, currentCase.i18n);
|
|
27575
27752
|
const expression = currentCase.expression === null ?
|
|
27576
27753
|
null :
|
|
27577
27754
|
currentCase.expression.visit(this._valueConverter);
|
|
@@ -27619,23 +27796,21 @@ class TemplateDefinitionBuilder {
|
|
|
27619
27796
|
if (!metadata) {
|
|
27620
27797
|
throw new Error('Could not resolve `defer` block metadata. Block may need to be analyzed.');
|
|
27621
27798
|
}
|
|
27622
|
-
const primaryTemplateIndex = this.createEmbeddedTemplateFn(null, deferred.children, '_Defer', deferred.sourceSpan);
|
|
27623
|
-
const loadingIndex = loading ?
|
|
27624
|
-
this.createEmbeddedTemplateFn(null, loading.children, '_DeferLoading', loading.sourceSpan) :
|
|
27799
|
+
const primaryTemplateIndex = this.createEmbeddedTemplateFn(null, deferred.children, '_Defer', deferred.sourceSpan, undefined, undefined, undefined, deferred.i18n);
|
|
27800
|
+
const loadingIndex = loading ? this.createEmbeddedTemplateFn(null, loading.children, '_DeferLoading', loading.sourceSpan, undefined, undefined, undefined, loading.i18n) :
|
|
27625
27801
|
null;
|
|
27626
27802
|
const loadingConsts = loading ?
|
|
27627
27803
|
trimTrailingNulls([literal(loading.minimumTime), literal(loading.afterTime)]) :
|
|
27628
27804
|
null;
|
|
27629
27805
|
const placeholderIndex = placeholder ?
|
|
27630
|
-
this.createEmbeddedTemplateFn(null, placeholder.children, '_DeferPlaceholder', placeholder.sourceSpan) :
|
|
27806
|
+
this.createEmbeddedTemplateFn(null, placeholder.children, '_DeferPlaceholder', placeholder.sourceSpan, undefined, undefined, undefined, placeholder.i18n) :
|
|
27631
27807
|
null;
|
|
27632
27808
|
const placeholderConsts = placeholder && placeholder.minimumTime !== null ?
|
|
27633
27809
|
// TODO(crisbeto): potentially pass the time directly instead of storing it in the `consts`
|
|
27634
27810
|
// since the placeholder block can only have one parameter?
|
|
27635
27811
|
literalArr([literal(placeholder.minimumTime)]) :
|
|
27636
27812
|
null;
|
|
27637
|
-
const errorIndex = error ?
|
|
27638
|
-
this.createEmbeddedTemplateFn(null, error.children, '_DeferError', error.sourceSpan) :
|
|
27813
|
+
const errorIndex = error ? this.createEmbeddedTemplateFn(null, error.children, '_DeferError', error.sourceSpan, undefined, undefined, undefined, error.i18n) :
|
|
27639
27814
|
null;
|
|
27640
27815
|
// Note: we generate this last so the index matches the instruction order.
|
|
27641
27816
|
const deferredIndex = this.allocateDataSlot();
|
|
@@ -27789,11 +27964,18 @@ class TemplateDefinitionBuilder {
|
|
|
27789
27964
|
// are implicitly inferred by the runtime to index + 1 and index + 2.
|
|
27790
27965
|
const blockIndex = this.allocateDataSlot();
|
|
27791
27966
|
const { tagName, attrsExprs } = this.inferProjectionDataFromInsertionPoint(block);
|
|
27792
|
-
const primaryData = this.prepareEmbeddedTemplateFn(block.children, '_For', [block.item, block.contextVariables.$index, block.contextVariables.$count]
|
|
27967
|
+
const primaryData = this.prepareEmbeddedTemplateFn(block.children, '_For', [block.item, block.contextVariables.$index, block.contextVariables.$count], block.i18n, {
|
|
27968
|
+
// We need to provide level-specific versions of `$index` and `$count`, because
|
|
27969
|
+
// they're used when deriving the remaining variables (`$odd`, `$even` etc.) while at the
|
|
27970
|
+
// same time being available implicitly. Without these aliases, we wouldn't be able to
|
|
27971
|
+
// access the `$index` of a parent loop from inside of a nested loop.
|
|
27972
|
+
[block.contextVariables.$index.name]: this.getLevelSpecificVariableName('$index', this.level + 1),
|
|
27973
|
+
[block.contextVariables.$count.name]: this.getLevelSpecificVariableName('$count', this.level + 1),
|
|
27974
|
+
});
|
|
27793
27975
|
const { expression: trackByExpression, usesComponentInstance: trackByUsesComponentInstance } = this.createTrackByFunction(block);
|
|
27794
27976
|
let emptyData = null;
|
|
27795
27977
|
if (block.empty !== null) {
|
|
27796
|
-
emptyData = this.prepareEmbeddedTemplateFn(block.empty.children, '_ForEmpty');
|
|
27978
|
+
emptyData = this.prepareEmbeddedTemplateFn(block.empty.children, '_ForEmpty', undefined, block.empty.i18n);
|
|
27797
27979
|
// Allocate an extra slot for the empty block tracking.
|
|
27798
27980
|
this.allocateBindingSlots(null);
|
|
27799
27981
|
}
|
|
@@ -27823,17 +28005,44 @@ class TemplateDefinitionBuilder {
|
|
|
27823
28005
|
// Note: we don't allocate binding slots for this expression,
|
|
27824
28006
|
// because its value isn't stored in the LView.
|
|
27825
28007
|
const value = block.expression.visit(this._valueConverter);
|
|
27826
|
-
// `repeater(
|
|
27827
|
-
this.
|
|
28008
|
+
// `advance(x); repeater(iterable)`
|
|
28009
|
+
this.updateInstructionWithAdvance(blockIndex, block.sourceSpan, Identifiers.repeater, () => [this.convertPropertyBinding(value)]);
|
|
27828
28010
|
}
|
|
27829
28011
|
registerComputedLoopVariables(block, bindingScope) {
|
|
27830
|
-
const indexLocalName = block.contextVariables.$index.name;
|
|
27831
|
-
const countLocalName = block.contextVariables.$count.name;
|
|
27832
28012
|
const level = bindingScope.bindingLevel;
|
|
27833
|
-
bindingScope.set(level, block.contextVariables.$odd.name, scope =>
|
|
27834
|
-
|
|
27835
|
-
|
|
27836
|
-
|
|
28013
|
+
bindingScope.set(level, block.contextVariables.$odd.name, (scope, retrievalLevel) => {
|
|
28014
|
+
return this.getLevelSpecificForLoopVariable(block, scope, retrievalLevel, '$index')
|
|
28015
|
+
.modulo(literal(2))
|
|
28016
|
+
.notIdentical(literal(0));
|
|
28017
|
+
});
|
|
28018
|
+
bindingScope.set(level, block.contextVariables.$even.name, (scope, retrievalLevel) => {
|
|
28019
|
+
return this.getLevelSpecificForLoopVariable(block, scope, retrievalLevel, '$index')
|
|
28020
|
+
.modulo(literal(2))
|
|
28021
|
+
.identical(literal(0));
|
|
28022
|
+
});
|
|
28023
|
+
bindingScope.set(level, block.contextVariables.$first.name, (scope, retrievalLevel) => {
|
|
28024
|
+
return this.getLevelSpecificForLoopVariable(block, scope, retrievalLevel, '$index')
|
|
28025
|
+
.identical(literal(0));
|
|
28026
|
+
});
|
|
28027
|
+
bindingScope.set(level, block.contextVariables.$last.name, (scope, retrievalLevel) => {
|
|
28028
|
+
const index = this.getLevelSpecificForLoopVariable(block, scope, retrievalLevel, '$index');
|
|
28029
|
+
const count = this.getLevelSpecificForLoopVariable(block, scope, retrievalLevel, '$count');
|
|
28030
|
+
return index.identical(count.minus(literal(1)));
|
|
28031
|
+
});
|
|
28032
|
+
}
|
|
28033
|
+
getLevelSpecificVariableName(name, level) {
|
|
28034
|
+
// We use the `ɵ` here to ensure that there are no name conflicts with user-defined variables.
|
|
28035
|
+
return `ɵ${name}_${level}`;
|
|
28036
|
+
}
|
|
28037
|
+
/**
|
|
28038
|
+
* Gets the name of a for loop variable at a specific binding level. This allows us to look
|
|
28039
|
+
* up implicitly shadowed variables like `$index` and `$count` at a specific level.
|
|
28040
|
+
*/
|
|
28041
|
+
getLevelSpecificForLoopVariable(block, scope, retrievalLevel, name) {
|
|
28042
|
+
const scopeName = scope.bindingLevel === retrievalLevel ?
|
|
28043
|
+
block.contextVariables[name].name :
|
|
28044
|
+
this.getLevelSpecificVariableName(name, retrievalLevel);
|
|
28045
|
+
return scope.get(scopeName);
|
|
27837
28046
|
}
|
|
27838
28047
|
optimizeTrackByFunction(block) {
|
|
27839
28048
|
const indexLocalName = block.contextVariables.$index.name;
|
|
@@ -28371,7 +28580,7 @@ class BindingScope {
|
|
|
28371
28580
|
if (value.declareLocalCallback && !value.declare) {
|
|
28372
28581
|
value.declare = true;
|
|
28373
28582
|
}
|
|
28374
|
-
return typeof value.lhs === 'function' ? value.lhs(this) : value.lhs;
|
|
28583
|
+
return typeof value.lhs === 'function' ? value.lhs(this, value.retrievalLevel) : value.lhs;
|
|
28375
28584
|
}
|
|
28376
28585
|
current = current.parent;
|
|
28377
28586
|
}
|
|
@@ -28479,7 +28688,9 @@ class BindingScope {
|
|
|
28479
28688
|
const componentValue = this.map.get(SHARED_CONTEXT_KEY + 0);
|
|
28480
28689
|
componentValue.declare = true;
|
|
28481
28690
|
this.maybeRestoreView();
|
|
28482
|
-
const lhs = typeof componentValue.lhs === 'function' ?
|
|
28691
|
+
const lhs = typeof componentValue.lhs === 'function' ?
|
|
28692
|
+
componentValue.lhs(this, componentValue.retrievalLevel) :
|
|
28693
|
+
componentValue.lhs;
|
|
28483
28694
|
return name === DIRECT_CONTEXT_REFERENCE ? lhs : lhs.prop(name);
|
|
28484
28695
|
}
|
|
28485
28696
|
maybeRestoreView() {
|
|
@@ -28951,6 +29162,11 @@ function addFeatures(definitionMap, meta) {
|
|
|
28951
29162
|
break;
|
|
28952
29163
|
}
|
|
28953
29164
|
}
|
|
29165
|
+
// Note: host directives feature needs to be inserted before the
|
|
29166
|
+
// inheritance feature to ensure the correct execution order.
|
|
29167
|
+
if (meta.hostDirectives?.length) {
|
|
29168
|
+
features.push(importExpr(Identifiers.HostDirectivesFeature).callFn([createHostDirectivesFeatureArg(meta.hostDirectives)]));
|
|
29169
|
+
}
|
|
28954
29170
|
if (meta.usesInheritance) {
|
|
28955
29171
|
features.push(importExpr(Identifiers.InheritDefinitionFeature));
|
|
28956
29172
|
}
|
|
@@ -28964,9 +29180,6 @@ function addFeatures(definitionMap, meta) {
|
|
|
28964
29180
|
if (meta.hasOwnProperty('template') && meta.isStandalone) {
|
|
28965
29181
|
features.push(importExpr(Identifiers.StandaloneFeature));
|
|
28966
29182
|
}
|
|
28967
|
-
if (meta.hostDirectives?.length) {
|
|
28968
|
-
features.push(importExpr(Identifiers.HostDirectivesFeature).callFn([createHostDirectivesFeatureArg(meta.hostDirectives)]));
|
|
28969
|
-
}
|
|
28970
29183
|
if (features.length) {
|
|
28971
29184
|
definitionMap.set('features', literalArr(features));
|
|
28972
29185
|
}
|
|
@@ -31064,7 +31277,7 @@ function publishFacade(global) {
|
|
|
31064
31277
|
* @description
|
|
31065
31278
|
* Entry point for all public APIs of the compiler package.
|
|
31066
31279
|
*/
|
|
31067
|
-
const VERSION = new Version('17.0.
|
|
31280
|
+
const VERSION = new Version('17.0.5');
|
|
31068
31281
|
|
|
31069
31282
|
class CompilerConfig {
|
|
31070
31283
|
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
@@ -31297,7 +31510,8 @@ class _Visitor {
|
|
|
31297
31510
|
this._errors = [];
|
|
31298
31511
|
this._messages = [];
|
|
31299
31512
|
this._inImplicitNode = false;
|
|
31300
|
-
this._createI18nMessage =
|
|
31513
|
+
this._createI18nMessage =
|
|
31514
|
+
createI18nMessageFactory(interpolationConfig, DEFAULT_CONTAINER_BLOCKS);
|
|
31301
31515
|
}
|
|
31302
31516
|
// looks for translatable attributes
|
|
31303
31517
|
_visitAttributesOf(el) {
|
|
@@ -31605,6 +31819,12 @@ class _WriteVisitor$1 {
|
|
|
31605
31819
|
visitPlaceholder(ph, context) {
|
|
31606
31820
|
return [new Tag(_PLACEHOLDER_TAG$2, { id: ph.name, 'equiv-text': `{{${ph.value}}}` })];
|
|
31607
31821
|
}
|
|
31822
|
+
visitBlockPlaceholder(ph, context) {
|
|
31823
|
+
const ctype = `x-${ph.name.toLowerCase().replace(/[^a-z0-9]/g, '-')}`;
|
|
31824
|
+
const startTagPh = new Tag(_PLACEHOLDER_TAG$2, { id: ph.startName, ctype, 'equiv-text': `@${ph.name}` });
|
|
31825
|
+
const closeTagPh = new Tag(_PLACEHOLDER_TAG$2, { id: ph.closeName, ctype, 'equiv-text': `}` });
|
|
31826
|
+
return [startTagPh, ...this.serialize(ph.children), closeTagPh];
|
|
31827
|
+
}
|
|
31608
31828
|
visitIcuPlaceholder(ph, context) {
|
|
31609
31829
|
const equivText = `{${ph.value.expression}, ${ph.value.type}, ${Object.keys(ph.value.cases).map((value) => value + ' {...}').join(' ')}}`;
|
|
31610
31830
|
return [new Tag(_PLACEHOLDER_TAG$2, { id: ph.name, 'equiv-text': equivText })];
|
|
@@ -31876,6 +32096,24 @@ class _WriteVisitor {
|
|
|
31876
32096
|
disp: `{{${ph.value}}}`,
|
|
31877
32097
|
})];
|
|
31878
32098
|
}
|
|
32099
|
+
visitBlockPlaceholder(ph, context) {
|
|
32100
|
+
const tagPc = new Tag(_PLACEHOLDER_SPANNING_TAG, {
|
|
32101
|
+
id: (this._nextPlaceholderId++).toString(),
|
|
32102
|
+
equivStart: ph.startName,
|
|
32103
|
+
equivEnd: ph.closeName,
|
|
32104
|
+
type: 'other',
|
|
32105
|
+
dispStart: `@${ph.name}`,
|
|
32106
|
+
dispEnd: `}`,
|
|
32107
|
+
});
|
|
32108
|
+
const nodes = [].concat(...ph.children.map(node => node.visit(this)));
|
|
32109
|
+
if (nodes.length) {
|
|
32110
|
+
nodes.forEach((node) => tagPc.children.push(node));
|
|
32111
|
+
}
|
|
32112
|
+
else {
|
|
32113
|
+
tagPc.children.push(new Text$1(''));
|
|
32114
|
+
}
|
|
32115
|
+
return [tagPc];
|
|
32116
|
+
}
|
|
31879
32117
|
visitIcuPlaceholder(ph, context) {
|
|
31880
32118
|
const cases = Object.keys(ph.value.cases).map((value) => value + ' {...}').join(' ');
|
|
31881
32119
|
const idStr = (this._nextPlaceholderId++).toString();
|
|
@@ -32324,6 +32562,11 @@ class I18nToHtmlVisitor {
|
|
|
32324
32562
|
// An ICU placeholder references the source message to be serialized
|
|
32325
32563
|
return this._convertToText(this._srcMsg.placeholderToMessage[ph.name]);
|
|
32326
32564
|
}
|
|
32565
|
+
visitBlockPlaceholder(ph, context) {
|
|
32566
|
+
const params = ph.parameters.length === 0 ? '' : ` (${ph.parameters.join('; ')})`;
|
|
32567
|
+
const children = ph.children.map((c) => c.visit(this)).join('');
|
|
32568
|
+
return `@${ph.name}${params} {${children}}`;
|
|
32569
|
+
}
|
|
32327
32570
|
/**
|
|
32328
32571
|
* Convert a source message to a translated text string:
|
|
32329
32572
|
* - text nodes are replaced with their translation,
|
|
@@ -32476,6 +32719,12 @@ class MapPlaceholderNames extends CloneVisitor {
|
|
|
32476
32719
|
const children = ph.children.map(n => n.visit(this, mapper));
|
|
32477
32720
|
return new TagPlaceholder(ph.tag, ph.attrs, startName, closeName, children, ph.isVoid, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan);
|
|
32478
32721
|
}
|
|
32722
|
+
visitBlockPlaceholder(ph, mapper) {
|
|
32723
|
+
const startName = mapper.toPublicName(ph.startName);
|
|
32724
|
+
const closeName = ph.closeName ? mapper.toPublicName(ph.closeName) : ph.closeName;
|
|
32725
|
+
const children = ph.children.map(n => n.visit(this, mapper));
|
|
32726
|
+
return new BlockPlaceholder(ph.name, ph.parameters, startName, closeName, children, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan);
|
|
32727
|
+
}
|
|
32479
32728
|
visitPlaceholder(ph, mapper) {
|
|
32480
32729
|
return new Placeholder(ph.value, mapper.toPublicName(ph.name), ph.sourceSpan);
|
|
32481
32730
|
}
|
|
@@ -32594,7 +32843,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
|
|
|
32594
32843
|
function compileDeclareClassMetadata(metadata) {
|
|
32595
32844
|
const definitionMap = new DefinitionMap();
|
|
32596
32845
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
32597
|
-
definitionMap.set('version', literal('17.0.
|
|
32846
|
+
definitionMap.set('version', literal('17.0.5'));
|
|
32598
32847
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
32599
32848
|
definitionMap.set('type', metadata.type);
|
|
32600
32849
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -32702,7 +32951,7 @@ function createDirectiveDefinitionMap(meta) {
|
|
|
32702
32951
|
// in 16.1 is actually used.
|
|
32703
32952
|
const minVersion = hasTransformFunctions ? MINIMUM_PARTIAL_LINKER_VERSION$5 : '14.0.0';
|
|
32704
32953
|
definitionMap.set('minVersion', literal(minVersion));
|
|
32705
|
-
definitionMap.set('version', literal('17.0.
|
|
32954
|
+
definitionMap.set('version', literal('17.0.5'));
|
|
32706
32955
|
// e.g. `type: MyDirective`
|
|
32707
32956
|
definitionMap.set('type', meta.type.value);
|
|
32708
32957
|
if (meta.isStandalone) {
|
|
@@ -32979,7 +33228,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
32979
33228
|
function compileDeclareFactoryFunction(meta) {
|
|
32980
33229
|
const definitionMap = new DefinitionMap();
|
|
32981
33230
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
32982
|
-
definitionMap.set('version', literal('17.0.
|
|
33231
|
+
definitionMap.set('version', literal('17.0.5'));
|
|
32983
33232
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
32984
33233
|
definitionMap.set('type', meta.type.value);
|
|
32985
33234
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -33014,7 +33263,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
33014
33263
|
function createInjectableDefinitionMap(meta) {
|
|
33015
33264
|
const definitionMap = new DefinitionMap();
|
|
33016
33265
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
33017
|
-
definitionMap.set('version', literal('17.0.
|
|
33266
|
+
definitionMap.set('version', literal('17.0.5'));
|
|
33018
33267
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33019
33268
|
definitionMap.set('type', meta.type.value);
|
|
33020
33269
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -33065,7 +33314,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
33065
33314
|
function createInjectorDefinitionMap(meta) {
|
|
33066
33315
|
const definitionMap = new DefinitionMap();
|
|
33067
33316
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
33068
|
-
definitionMap.set('version', literal('17.0.
|
|
33317
|
+
definitionMap.set('version', literal('17.0.5'));
|
|
33069
33318
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33070
33319
|
definitionMap.set('type', meta.type.value);
|
|
33071
33320
|
definitionMap.set('providers', meta.providers);
|
|
@@ -33098,7 +33347,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
33098
33347
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
33099
33348
|
}
|
|
33100
33349
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
33101
|
-
definitionMap.set('version', literal('17.0.
|
|
33350
|
+
definitionMap.set('version', literal('17.0.5'));
|
|
33102
33351
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33103
33352
|
definitionMap.set('type', meta.type.value);
|
|
33104
33353
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -33149,7 +33398,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
33149
33398
|
function createPipeDefinitionMap(meta) {
|
|
33150
33399
|
const definitionMap = new DefinitionMap();
|
|
33151
33400
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
33152
|
-
definitionMap.set('version', literal('17.0.
|
|
33401
|
+
definitionMap.set('version', literal('17.0.5'));
|
|
33153
33402
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33154
33403
|
// e.g. `type: MyPipe`
|
|
33155
33404
|
definitionMap.set('type', meta.type.value);
|