@angular/compiler 17.1.0-next.4 → 17.1.0-next.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/constant_pool.mjs +5 -3
- package/esm2022/src/ml_parser/tags.mjs +8 -3
- package/esm2022/src/render3/partial/class_metadata.mjs +1 -1
- package/esm2022/src/render3/partial/directive.mjs +1 -1
- package/esm2022/src/render3/partial/factory.mjs +1 -1
- package/esm2022/src/render3/partial/injectable.mjs +1 -1
- package/esm2022/src/render3/partial/injector.mjs +1 -1
- package/esm2022/src/render3/partial/ng_module.mjs +1 -1
- package/esm2022/src/render3/partial/pipe.mjs +1 -1
- package/esm2022/src/render3/view/template.mjs +14 -9
- package/esm2022/src/template/pipeline/ir/src/enums.mjs +7 -3
- package/esm2022/src/template/pipeline/ir/src/expression.mjs +15 -1
- package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +35 -13
- package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +4 -2
- package/esm2022/src/template/pipeline/src/emit.mjs +3 -3
- package/esm2022/src/template/pipeline/src/ingest.mjs +67 -41
- package/esm2022/src/template/pipeline/src/instruction.mjs +17 -11
- package/esm2022/src/template/pipeline/src/phases/attribute_extraction.mjs +10 -15
- package/esm2022/src/template/pipeline/src/phases/const_collection.mjs +48 -12
- package/esm2022/src/template/pipeline/src/phases/convert_i18n_bindings.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/create_defer_deps_fns.mjs +3 -2
- package/esm2022/src/template/pipeline/src/phases/create_i18n_contexts.mjs +63 -51
- package/esm2022/src/template/pipeline/src/phases/deduplicate_text_bindings.mjs +40 -0
- package/esm2022/src/template/pipeline/src/phases/extract_i18n_messages.mjs +52 -49
- package/esm2022/src/template/pipeline/src/phases/host_style_property_parsing.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/i18n_const_collection.mjs +2 -3
- package/esm2022/src/template/pipeline/src/phases/i18n_text_extraction.mjs +22 -3
- package/esm2022/src/template/pipeline/src/phases/naming.mjs +13 -5
- package/esm2022/src/template/pipeline/src/phases/ordering.mjs +17 -5
- package/esm2022/src/template/pipeline/src/phases/parse_extracted_styles.mjs +19 -1
- package/esm2022/src/template/pipeline/src/phases/phase_remove_content_selectors.mjs +1 -10
- package/esm2022/src/template/pipeline/src/phases/propagate_i18n_blocks.mjs +5 -3
- package/esm2022/src/template/pipeline/src/phases/reify.mjs +36 -11
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_expression_placeholders.mjs +23 -10
- package/esm2022/src/template/pipeline/src/phases/track_fn_generation.mjs +4 -1
- package/esm2022/src/template/pipeline/src/phases/var_counting.mjs +8 -1
- package/esm2022/src/template/pipeline/src/phases/wrap_icus.mjs +4 -3
- package/esm2022/src/template/pipeline/src/util/elements.mjs +8 -1
- package/esm2022/src/version.mjs +1 -1
- package/fesm2022/compiler.mjs +518 -302
- package/fesm2022/compiler.mjs.map +1 -1
- package/index.d.ts +3 -3
- package/package.json +2 -2
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_icu_placeholders.mjs +0 -62
package/fesm2022/compiler.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v17.1.0-next.
|
|
2
|
+
* @license Angular v17.1.0-next.5
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -2308,7 +2308,9 @@ class ConstantPool {
|
|
|
2308
2308
|
}))));
|
|
2309
2309
|
}
|
|
2310
2310
|
}
|
|
2311
|
-
|
|
2311
|
+
// TODO: useUniqueName(false) is necessary for naming compatibility with
|
|
2312
|
+
// TemplateDefinitionBuilder, but should be removed once Template Pipeline is the default.
|
|
2313
|
+
getSharedFunctionReference(fn, prefix, useUniqueName = true) {
|
|
2312
2314
|
const isArrow = fn instanceof ArrowFunctionExpr;
|
|
2313
2315
|
for (const current of this.statements) {
|
|
2314
2316
|
// Arrow functions are saved as variables so we check if the
|
|
@@ -2323,7 +2325,7 @@ class ConstantPool {
|
|
|
2323
2325
|
}
|
|
2324
2326
|
}
|
|
2325
2327
|
// Otherwise declare the function.
|
|
2326
|
-
const name = this.uniqueName(prefix);
|
|
2328
|
+
const name = useUniqueName ? this.uniqueName(prefix) : prefix;
|
|
2327
2329
|
this.statements.push(fn.toDeclStmt(name, StmtModifier.Final));
|
|
2328
2330
|
return variable(name);
|
|
2329
2331
|
}
|
|
@@ -3688,13 +3690,18 @@ var TagContentType;
|
|
|
3688
3690
|
TagContentType[TagContentType["ESCAPABLE_RAW_TEXT"] = 1] = "ESCAPABLE_RAW_TEXT";
|
|
3689
3691
|
TagContentType[TagContentType["PARSABLE_DATA"] = 2] = "PARSABLE_DATA";
|
|
3690
3692
|
})(TagContentType || (TagContentType = {}));
|
|
3691
|
-
function splitNsName(elementName) {
|
|
3693
|
+
function splitNsName(elementName, fatal = true) {
|
|
3692
3694
|
if (elementName[0] != ':') {
|
|
3693
3695
|
return [null, elementName];
|
|
3694
3696
|
}
|
|
3695
3697
|
const colonIndex = elementName.indexOf(':', 1);
|
|
3696
3698
|
if (colonIndex === -1) {
|
|
3697
|
-
|
|
3699
|
+
if (fatal) {
|
|
3700
|
+
throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
|
|
3701
|
+
}
|
|
3702
|
+
else {
|
|
3703
|
+
return [null, elementName];
|
|
3704
|
+
}
|
|
3698
3705
|
}
|
|
3699
3706
|
return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
|
|
3700
3707
|
}
|
|
@@ -8975,14 +8982,18 @@ var OpKind;
|
|
|
8975
8982
|
* An instruction to update an ICU expression.
|
|
8976
8983
|
*/
|
|
8977
8984
|
OpKind[OpKind["IcuEnd"] = 42] = "IcuEnd";
|
|
8985
|
+
/**
|
|
8986
|
+
* An instruction representing a placeholder in an ICU expression.
|
|
8987
|
+
*/
|
|
8988
|
+
OpKind[OpKind["IcuPlaceholder"] = 43] = "IcuPlaceholder";
|
|
8978
8989
|
/**
|
|
8979
8990
|
* An i18n context containing information needed to generate an i18n message.
|
|
8980
8991
|
*/
|
|
8981
|
-
OpKind[OpKind["I18nContext"] =
|
|
8992
|
+
OpKind[OpKind["I18nContext"] = 44] = "I18nContext";
|
|
8982
8993
|
/**
|
|
8983
8994
|
* A creation op that corresponds to i18n attributes on an element.
|
|
8984
8995
|
*/
|
|
8985
|
-
OpKind[OpKind["I18nAttributes"] =
|
|
8996
|
+
OpKind[OpKind["I18nAttributes"] = 45] = "I18nAttributes";
|
|
8986
8997
|
})(OpKind || (OpKind = {}));
|
|
8987
8998
|
/**
|
|
8988
8999
|
* Distinguishes different kinds of IR expressions.
|
|
@@ -9581,12 +9592,13 @@ function createDeferWhenOp(target, expr, prefetch, sourceSpan) {
|
|
|
9581
9592
|
sourceSpan,
|
|
9582
9593
|
...NEW_OP,
|
|
9583
9594
|
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9595
|
+
...TRAIT_CONSUMES_VARS,
|
|
9584
9596
|
};
|
|
9585
9597
|
}
|
|
9586
9598
|
/**
|
|
9587
9599
|
* Create an i18n expression op.
|
|
9588
9600
|
*/
|
|
9589
|
-
function createI18nExpressionOp(context, target, i18nOwner, handle, expression, i18nPlaceholder, resolutionTime, usage, name, sourceSpan) {
|
|
9601
|
+
function createI18nExpressionOp(context, target, i18nOwner, handle, expression, icuPlaceholder, i18nPlaceholder, resolutionTime, usage, name, sourceSpan) {
|
|
9590
9602
|
return {
|
|
9591
9603
|
kind: OpKind.I18nExpression,
|
|
9592
9604
|
context,
|
|
@@ -9594,6 +9606,7 @@ function createI18nExpressionOp(context, target, i18nOwner, handle, expression,
|
|
|
9594
9606
|
i18nOwner,
|
|
9595
9607
|
handle,
|
|
9596
9608
|
expression,
|
|
9609
|
+
icuPlaceholder,
|
|
9597
9610
|
i18nPlaceholder,
|
|
9598
9611
|
resolutionTime,
|
|
9599
9612
|
usage,
|
|
@@ -10363,6 +10376,9 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
10363
10376
|
op.placeholderConfig =
|
|
10364
10377
|
transformExpressionsInExpression(op.placeholderConfig, transform, flags);
|
|
10365
10378
|
}
|
|
10379
|
+
if (op.resolverFn !== null) {
|
|
10380
|
+
op.resolverFn = transformExpressionsInExpression(op.resolverFn, transform, flags);
|
|
10381
|
+
}
|
|
10366
10382
|
break;
|
|
10367
10383
|
case OpKind.I18nMessage:
|
|
10368
10384
|
for (const [placeholder, expr] of op.params) {
|
|
@@ -10399,6 +10415,7 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
10399
10415
|
case OpKind.Template:
|
|
10400
10416
|
case OpKind.Text:
|
|
10401
10417
|
case OpKind.I18nAttributes:
|
|
10418
|
+
case OpKind.IcuPlaceholder:
|
|
10402
10419
|
// These operations contain no expressions.
|
|
10403
10420
|
break;
|
|
10404
10421
|
default:
|
|
@@ -10481,6 +10498,16 @@ function transformExpressionsInExpression(expr, transform, flags) {
|
|
|
10481
10498
|
expr.template.expressions =
|
|
10482
10499
|
expr.template.expressions.map(e => transformExpressionsInExpression(e, transform, flags));
|
|
10483
10500
|
}
|
|
10501
|
+
else if (expr instanceof ArrowFunctionExpr) {
|
|
10502
|
+
if (Array.isArray(expr.body)) {
|
|
10503
|
+
for (let i = 0; i < expr.body.length; i++) {
|
|
10504
|
+
transformExpressionsInStatement(expr.body[i], transform, flags);
|
|
10505
|
+
}
|
|
10506
|
+
}
|
|
10507
|
+
else {
|
|
10508
|
+
expr.body = transformExpressionsInExpression(expr.body, transform, flags);
|
|
10509
|
+
}
|
|
10510
|
+
}
|
|
10484
10511
|
else if (expr instanceof WrappedNodeExpr) {
|
|
10485
10512
|
// TODO: Do we need to transform any TS nodes nested inside of this expression?
|
|
10486
10513
|
}
|
|
@@ -10806,7 +10833,7 @@ function isElementOrContainerOp(op) {
|
|
|
10806
10833
|
/**
|
|
10807
10834
|
* Create an `ElementStartOp`.
|
|
10808
10835
|
*/
|
|
10809
|
-
function createElementStartOp(tag, xref, namespace, i18nPlaceholder,
|
|
10836
|
+
function createElementStartOp(tag, xref, namespace, i18nPlaceholder, startSourceSpan, wholeSourceSpan) {
|
|
10810
10837
|
return {
|
|
10811
10838
|
kind: OpKind.ElementStart,
|
|
10812
10839
|
xref,
|
|
@@ -10817,7 +10844,8 @@ function createElementStartOp(tag, xref, namespace, i18nPlaceholder, sourceSpan)
|
|
|
10817
10844
|
nonBindable: false,
|
|
10818
10845
|
namespace,
|
|
10819
10846
|
i18nPlaceholder,
|
|
10820
|
-
|
|
10847
|
+
startSourceSpan,
|
|
10848
|
+
wholeSourceSpan,
|
|
10821
10849
|
...TRAIT_CONSUMES_SLOT,
|
|
10822
10850
|
...NEW_OP,
|
|
10823
10851
|
};
|
|
@@ -10825,7 +10853,7 @@ function createElementStartOp(tag, xref, namespace, i18nPlaceholder, sourceSpan)
|
|
|
10825
10853
|
/**
|
|
10826
10854
|
* Create a `TemplateOp`.
|
|
10827
10855
|
*/
|
|
10828
|
-
function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace, i18nPlaceholder,
|
|
10856
|
+
function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace, i18nPlaceholder, startSourceSpan, wholeSourceSpan) {
|
|
10829
10857
|
return {
|
|
10830
10858
|
kind: OpKind.Template,
|
|
10831
10859
|
xref,
|
|
@@ -10840,12 +10868,13 @@ function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace
|
|
|
10840
10868
|
nonBindable: false,
|
|
10841
10869
|
namespace,
|
|
10842
10870
|
i18nPlaceholder,
|
|
10843
|
-
|
|
10871
|
+
startSourceSpan,
|
|
10872
|
+
wholeSourceSpan,
|
|
10844
10873
|
...TRAIT_CONSUMES_SLOT,
|
|
10845
10874
|
...NEW_OP,
|
|
10846
10875
|
};
|
|
10847
10876
|
}
|
|
10848
|
-
function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, i18nPlaceholder, emptyI18nPlaceholder,
|
|
10877
|
+
function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, emptyTag, i18nPlaceholder, emptyI18nPlaceholder, startSourceSpan, wholeSourceSpan) {
|
|
10849
10878
|
return {
|
|
10850
10879
|
kind: OpKind.RepeaterCreate,
|
|
10851
10880
|
attributes: null,
|
|
@@ -10855,6 +10884,8 @@ function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, i1
|
|
|
10855
10884
|
track,
|
|
10856
10885
|
trackByFn: null,
|
|
10857
10886
|
tag,
|
|
10887
|
+
emptyTag,
|
|
10888
|
+
emptyAttributes: null,
|
|
10858
10889
|
functionNameSuffix: 'For',
|
|
10859
10890
|
namespace: Namespace.HTML,
|
|
10860
10891
|
nonBindable: false,
|
|
@@ -10865,9 +10896,11 @@ function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, i1
|
|
|
10865
10896
|
usesComponentInstance: false,
|
|
10866
10897
|
i18nPlaceholder,
|
|
10867
10898
|
emptyI18nPlaceholder,
|
|
10868
|
-
|
|
10899
|
+
startSourceSpan,
|
|
10900
|
+
wholeSourceSpan,
|
|
10869
10901
|
...TRAIT_CONSUMES_SLOT,
|
|
10870
10902
|
...NEW_OP,
|
|
10903
|
+
...TRAIT_CONSUMES_VARS,
|
|
10871
10904
|
numSlotsUsed: emptyView === null ? 2 : 3,
|
|
10872
10905
|
};
|
|
10873
10906
|
}
|
|
@@ -10899,12 +10932,13 @@ function createEnableBindingsOp(xref) {
|
|
|
10899
10932
|
/**
|
|
10900
10933
|
* Create a `TextOp`.
|
|
10901
10934
|
*/
|
|
10902
|
-
function createTextOp(xref, initialValue, sourceSpan) {
|
|
10935
|
+
function createTextOp(xref, initialValue, icuPlaceholder, sourceSpan) {
|
|
10903
10936
|
return {
|
|
10904
10937
|
kind: OpKind.Text,
|
|
10905
10938
|
xref,
|
|
10906
10939
|
handle: new SlotHandle(),
|
|
10907
10940
|
initialValue,
|
|
10941
|
+
icuPlaceholder,
|
|
10908
10942
|
sourceSpan,
|
|
10909
10943
|
...TRAIT_CONSUMES_SLOT,
|
|
10910
10944
|
...NEW_OP,
|
|
@@ -10957,7 +10991,7 @@ function createProjectionDefOp(def) {
|
|
|
10957
10991
|
...NEW_OP,
|
|
10958
10992
|
};
|
|
10959
10993
|
}
|
|
10960
|
-
function createProjectionOp(xref, selector, i18nPlaceholder,
|
|
10994
|
+
function createProjectionOp(xref, selector, i18nPlaceholder, sourceSpan) {
|
|
10961
10995
|
return {
|
|
10962
10996
|
kind: OpKind.Projection,
|
|
10963
10997
|
xref,
|
|
@@ -10965,7 +10999,7 @@ function createProjectionOp(xref, selector, i18nPlaceholder, attributes, sourceS
|
|
|
10965
10999
|
selector,
|
|
10966
11000
|
i18nPlaceholder,
|
|
10967
11001
|
projectionSlotIndex: 0,
|
|
10968
|
-
attributes,
|
|
11002
|
+
attributes: null,
|
|
10969
11003
|
localRefs: [],
|
|
10970
11004
|
sourceSpan,
|
|
10971
11005
|
...NEW_OP,
|
|
@@ -11046,7 +11080,7 @@ function createI18nMessageOp(xref, i18nContext, i18nBlock, message, messagePlace
|
|
|
11046
11080
|
/**
|
|
11047
11081
|
* Create an `I18nStartOp`.
|
|
11048
11082
|
*/
|
|
11049
|
-
function createI18nStartOp(xref, message, root) {
|
|
11083
|
+
function createI18nStartOp(xref, message, root, sourceSpan) {
|
|
11050
11084
|
return {
|
|
11051
11085
|
kind: OpKind.I18nStart,
|
|
11052
11086
|
xref,
|
|
@@ -11056,6 +11090,7 @@ function createI18nStartOp(xref, message, root) {
|
|
|
11056
11090
|
messageIndex: null,
|
|
11057
11091
|
subTemplateIndex: null,
|
|
11058
11092
|
context: null,
|
|
11093
|
+
sourceSpan,
|
|
11059
11094
|
...NEW_OP,
|
|
11060
11095
|
...TRAIT_CONSUMES_SLOT,
|
|
11061
11096
|
};
|
|
@@ -11063,10 +11098,11 @@ function createI18nStartOp(xref, message, root) {
|
|
|
11063
11098
|
/**
|
|
11064
11099
|
* Create an `I18nEndOp`.
|
|
11065
11100
|
*/
|
|
11066
|
-
function createI18nEndOp(xref) {
|
|
11101
|
+
function createI18nEndOp(xref, sourceSpan) {
|
|
11067
11102
|
return {
|
|
11068
11103
|
kind: OpKind.I18nEnd,
|
|
11069
11104
|
xref,
|
|
11105
|
+
sourceSpan,
|
|
11070
11106
|
...NEW_OP,
|
|
11071
11107
|
};
|
|
11072
11108
|
}
|
|
@@ -11094,6 +11130,19 @@ function createIcuEndOp(xref) {
|
|
|
11094
11130
|
...NEW_OP,
|
|
11095
11131
|
};
|
|
11096
11132
|
}
|
|
11133
|
+
/**
|
|
11134
|
+
* Creates an ICU placeholder op.
|
|
11135
|
+
*/
|
|
11136
|
+
function createIcuPlaceholderOp(xref, name, strings) {
|
|
11137
|
+
return {
|
|
11138
|
+
kind: OpKind.IcuPlaceholder,
|
|
11139
|
+
xref,
|
|
11140
|
+
name,
|
|
11141
|
+
strings,
|
|
11142
|
+
expressionPlaceholders: [],
|
|
11143
|
+
...NEW_OP,
|
|
11144
|
+
};
|
|
11145
|
+
}
|
|
11097
11146
|
function createI18nContextOp(contextKind, xref, i18nBlock, message, sourceSpan) {
|
|
11098
11147
|
if (i18nBlock === null && contextKind !== I18nContextKind.Attr) {
|
|
11099
11148
|
throw new Error('AssertionError: i18nBlock must be provided for non-attribute contexts.');
|
|
@@ -11475,6 +11524,13 @@ function createOpXrefMap(unit) {
|
|
|
11475
11524
|
continue;
|
|
11476
11525
|
}
|
|
11477
11526
|
map.set(op.xref, op);
|
|
11527
|
+
// TODO(dylhunn): `@for` loops with `@empty` blocks need to be special-cased here,
|
|
11528
|
+
// because the slot consumer trait currently only supports one slot per consumer and we
|
|
11529
|
+
// need two. This should be revisited when making the refactors mentioned in:
|
|
11530
|
+
// https://github.com/angular/angular/pull/53620#discussion_r1430918822
|
|
11531
|
+
if (op.kind === OpKind.RepeaterCreate && op.emptyView !== null) {
|
|
11532
|
+
map.set(op.emptyView, op);
|
|
11533
|
+
}
|
|
11478
11534
|
}
|
|
11479
11535
|
return map;
|
|
11480
11536
|
}
|
|
@@ -11530,6 +11586,11 @@ function extractAttributes(job) {
|
|
|
11530
11586
|
/* i18nContext */ null,
|
|
11531
11587
|
/* i18nMessage */ null, SecurityContext.NONE);
|
|
11532
11588
|
if (job.kind === CompilationJobKind.Host) {
|
|
11589
|
+
if (job.compatibility) {
|
|
11590
|
+
// TemplateDefinitionBuilder does not extract listener bindings to the const array
|
|
11591
|
+
// (which is honestly pretty inconsistent).
|
|
11592
|
+
break;
|
|
11593
|
+
}
|
|
11533
11594
|
// This attribute will apply to the enclosing host binding compilation unit, so order
|
|
11534
11595
|
// doesn't matter.
|
|
11535
11596
|
unit.create.push(extractedAttributeOp);
|
|
@@ -11560,21 +11621,11 @@ function extractAttributeOp(unit, op, elements) {
|
|
|
11560
11621
|
if (op.expression instanceof Interpolation) {
|
|
11561
11622
|
return;
|
|
11562
11623
|
}
|
|
11563
|
-
let extractable = op.expression.isConstant();
|
|
11624
|
+
let extractable = op.isTextAttribute || op.expression.isConstant();
|
|
11564
11625
|
if (unit.job.compatibility === CompatibilityMode.TemplateDefinitionBuilder) {
|
|
11565
|
-
// TemplateDefinitionBuilder only
|
|
11566
|
-
|
|
11567
|
-
|
|
11568
|
-
// For style and class attributes, TemplateDefinitionBuilder only extracted them if they were
|
|
11569
|
-
// text attributes. For example, `[attr.class]="'my-class'"` was not extracted despite being a
|
|
11570
|
-
// string literal, because it is not a text attribute.
|
|
11571
|
-
extractable &&= op.isTextAttribute;
|
|
11572
|
-
}
|
|
11573
|
-
if (unit.job.kind === CompilationJobKind.Host) {
|
|
11574
|
-
// TemplateDefinitionBuilder also does not seem to extract string literals if they are part of
|
|
11575
|
-
// a host attribute.
|
|
11576
|
-
extractable &&= op.isTextAttribute;
|
|
11577
|
-
}
|
|
11626
|
+
// TemplateDefinitionBuilder only extracts text attributes. It does not extract attriibute
|
|
11627
|
+
// bindings, even if they are constants.
|
|
11628
|
+
extractable &&= op.isTextAttribute;
|
|
11578
11629
|
}
|
|
11579
11630
|
if (extractable) {
|
|
11580
11631
|
const extractedAttributeOp = createExtractedAttributeOp(op.target, op.isStructuralTemplateAttribute ? BindingKind.Template : BindingKind.Attribute, op.name, op.expression, op.i18nContext, op.i18nMessage, op.securityContext);
|
|
@@ -11868,7 +11919,7 @@ function collectElementConsts(job) {
|
|
|
11868
11919
|
for (const unit of job.units) {
|
|
11869
11920
|
for (const op of unit.create) {
|
|
11870
11921
|
if (op.kind === OpKind.ExtractedAttribute) {
|
|
11871
|
-
const attributes = allElementAttributes.get(op.target) || new ElementAttributes();
|
|
11922
|
+
const attributes = allElementAttributes.get(op.target) || new ElementAttributes(job.compatibility);
|
|
11872
11923
|
allElementAttributes.set(op.target, attributes);
|
|
11873
11924
|
attributes.add(op.bindingKind, op.name, op.expression, op.trustedValueFn);
|
|
11874
11925
|
OpList.remove(op);
|
|
@@ -11879,15 +11930,26 @@ function collectElementConsts(job) {
|
|
|
11879
11930
|
if (job instanceof ComponentCompilationJob) {
|
|
11880
11931
|
for (const unit of job.units) {
|
|
11881
11932
|
for (const op of unit.create) {
|
|
11882
|
-
|
|
11933
|
+
// TODO: Simplify and combine these cases.
|
|
11934
|
+
if (op.kind == OpKind.Projection) {
|
|
11883
11935
|
const attributes = allElementAttributes.get(op.xref);
|
|
11884
11936
|
if (attributes !== undefined) {
|
|
11885
11937
|
const attrArray = serializeAttributes(attributes);
|
|
11886
11938
|
if (attrArray.entries.length > 0) {
|
|
11887
|
-
op.attributes =
|
|
11939
|
+
op.attributes = attrArray;
|
|
11888
11940
|
}
|
|
11889
11941
|
}
|
|
11890
11942
|
}
|
|
11943
|
+
else if (isElementOrContainerOp(op)) {
|
|
11944
|
+
op.attributes = getConstIndex(job, allElementAttributes, op.xref);
|
|
11945
|
+
// TODO(dylhunn): `@for` loops with `@empty` blocks need to be special-cased here,
|
|
11946
|
+
// because the slot consumer trait currently only supports one slot per consumer and we
|
|
11947
|
+
// need two. This should be revisited when making the refactors mentioned in:
|
|
11948
|
+
// https://github.com/angular/angular/pull/53620#discussion_r1430918822
|
|
11949
|
+
if (op.kind === OpKind.RepeaterCreate && op.emptyView !== null) {
|
|
11950
|
+
op.emptyAttributes = getConstIndex(job, allElementAttributes, op.emptyView);
|
|
11951
|
+
}
|
|
11952
|
+
}
|
|
11891
11953
|
}
|
|
11892
11954
|
}
|
|
11893
11955
|
}
|
|
@@ -11905,6 +11967,16 @@ function collectElementConsts(job) {
|
|
|
11905
11967
|
}
|
|
11906
11968
|
}
|
|
11907
11969
|
}
|
|
11970
|
+
function getConstIndex(job, allElementAttributes, xref) {
|
|
11971
|
+
const attributes = allElementAttributes.get(xref);
|
|
11972
|
+
if (attributes !== undefined) {
|
|
11973
|
+
const attrArray = serializeAttributes(attributes);
|
|
11974
|
+
if (attrArray.entries.length > 0) {
|
|
11975
|
+
return job.addConst(attrArray);
|
|
11976
|
+
}
|
|
11977
|
+
}
|
|
11978
|
+
return null;
|
|
11979
|
+
}
|
|
11908
11980
|
/**
|
|
11909
11981
|
* Shared instance of an empty array to avoid unnecessary array allocations.
|
|
11910
11982
|
*/
|
|
@@ -11913,11 +11985,6 @@ const FLYWEIGHT_ARRAY = Object.freeze([]);
|
|
|
11913
11985
|
* Container for all of the various kinds of attributes which are applied on an element.
|
|
11914
11986
|
*/
|
|
11915
11987
|
class ElementAttributes {
|
|
11916
|
-
constructor() {
|
|
11917
|
-
this.known = new Set();
|
|
11918
|
-
this.byKind = new Map;
|
|
11919
|
-
this.projectAs = null;
|
|
11920
|
-
}
|
|
11921
11988
|
get attributes() {
|
|
11922
11989
|
return this.byKind.get(BindingKind.Attribute) ?? FLYWEIGHT_ARRAY;
|
|
11923
11990
|
}
|
|
@@ -11936,11 +12003,31 @@ class ElementAttributes {
|
|
|
11936
12003
|
get i18n() {
|
|
11937
12004
|
return this.byKind.get(BindingKind.I18n) ?? FLYWEIGHT_ARRAY;
|
|
11938
12005
|
}
|
|
12006
|
+
constructor(compatibility) {
|
|
12007
|
+
this.compatibility = compatibility;
|
|
12008
|
+
this.known = new Map();
|
|
12009
|
+
this.byKind = new Map;
|
|
12010
|
+
this.projectAs = null;
|
|
12011
|
+
}
|
|
12012
|
+
isKnown(kind, name, value) {
|
|
12013
|
+
const nameToValue = this.known.get(kind) ?? new Set();
|
|
12014
|
+
this.known.set(kind, nameToValue);
|
|
12015
|
+
if (nameToValue.has(name)) {
|
|
12016
|
+
return true;
|
|
12017
|
+
}
|
|
12018
|
+
nameToValue.add(name);
|
|
12019
|
+
return false;
|
|
12020
|
+
}
|
|
11939
12021
|
add(kind, name, value, trustedValueFn) {
|
|
11940
|
-
|
|
12022
|
+
// TemplateDefinitionBuilder puts duplicate attribute, class, and style values into the consts
|
|
12023
|
+
// array. This seems inefficient, we can probably keep just the first one or the last value
|
|
12024
|
+
// (whichever actually gets applied when multiple values are listed for the same attribute).
|
|
12025
|
+
const allowDuplicates = this.compatibility === CompatibilityMode.TemplateDefinitionBuilder &&
|
|
12026
|
+
(kind === BindingKind.Attribute || kind === BindingKind.ClassName ||
|
|
12027
|
+
kind === BindingKind.StyleProperty);
|
|
12028
|
+
if (!allowDuplicates && this.isKnown(kind, name, value)) {
|
|
11941
12029
|
return;
|
|
11942
12030
|
}
|
|
11943
|
-
this.known.add(name);
|
|
11944
12031
|
// TODO: Can this be its own phase
|
|
11945
12032
|
if (name === 'ngProjectAs') {
|
|
11946
12033
|
if (value === null || !(value instanceof LiteralExpr) || (value.value == null) ||
|
|
@@ -11979,7 +12066,7 @@ class ElementAttributes {
|
|
|
11979
12066
|
* Gets an array of literal expressions representing the attribute's namespaced name.
|
|
11980
12067
|
*/
|
|
11981
12068
|
function getAttributeNameLiterals$1(name) {
|
|
11982
|
-
const [attributeNamespace, attributeName] = splitNsName(name);
|
|
12069
|
+
const [attributeNamespace, attributeName] = splitNsName(name, false);
|
|
11983
12070
|
const nameLiteral = literal(attributeName);
|
|
11984
12071
|
if (attributeNamespace) {
|
|
11985
12072
|
return [
|
|
@@ -12052,7 +12139,7 @@ function convertI18nBindings(job) {
|
|
|
12052
12139
|
if (op.expression.i18nPlaceholders.length !== op.expression.expressions.length) {
|
|
12053
12140
|
throw new Error(`AssertionError: An i18n attribute binding instruction requires the same number of expressions and placeholders, but found ${op.expression.i18nPlaceholders.length} placeholders and ${op.expression.expressions.length} expressions`);
|
|
12054
12141
|
}
|
|
12055
|
-
ops.push(createI18nExpressionOp(op.i18nContext, i18nAttributesForElem.target, i18nAttributesForElem.xref, i18nAttributesForElem.handle, expr, op.expression.i18nPlaceholders[i], I18nParamResolutionTime.Creation, I18nExpressionFor.I18nAttribute, op.name, op.sourceSpan));
|
|
12142
|
+
ops.push(createI18nExpressionOp(op.i18nContext, i18nAttributesForElem.target, i18nAttributesForElem.xref, i18nAttributesForElem.handle, expr, null, op.expression.i18nPlaceholders[i], I18nParamResolutionTime.Creation, I18nExpressionFor.I18nAttribute, op.name, op.sourceSpan));
|
|
12056
12143
|
}
|
|
12057
12144
|
OpList.replaceWithMany(op, ops);
|
|
12058
12145
|
break;
|
|
@@ -12089,7 +12176,8 @@ function createDeferDepsFns(job) {
|
|
|
12089
12176
|
if (op.handle.slot === null) {
|
|
12090
12177
|
throw new Error('AssertionError: slot must be assigned bfore extracting defer deps functions');
|
|
12091
12178
|
}
|
|
12092
|
-
op.resolverFn = job.pool.getSharedFunctionReference(depsFnExpr, `${job.componentName}_Defer_${op.handle.slot}_DepsFn
|
|
12179
|
+
op.resolverFn = job.pool.getSharedFunctionReference(depsFnExpr, `${job.componentName}_Defer_${op.handle.slot}_DepsFn`,
|
|
12180
|
+
/* Don't use unique names for TDB compatibility */ false);
|
|
12093
12181
|
}
|
|
12094
12182
|
}
|
|
12095
12183
|
}
|
|
@@ -12106,75 +12194,119 @@ function createDeferDepsFns(job) {
|
|
|
12106
12194
|
* message.)
|
|
12107
12195
|
*/
|
|
12108
12196
|
function createI18nContexts(job) {
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12197
|
+
// Create i18n context ops for i18n attrs.
|
|
12198
|
+
const attrContextByMessage = new Map();
|
|
12199
|
+
for (const unit of job.units) {
|
|
12200
|
+
for (const op of unit.ops()) {
|
|
12201
|
+
switch (op.kind) {
|
|
12202
|
+
case OpKind.Binding:
|
|
12203
|
+
case OpKind.Property:
|
|
12204
|
+
case OpKind.Attribute:
|
|
12205
|
+
case OpKind.ExtractedAttribute:
|
|
12206
|
+
if (op.i18nMessage === null) {
|
|
12207
|
+
continue;
|
|
12208
|
+
}
|
|
12209
|
+
if (!attrContextByMessage.has(op.i18nMessage)) {
|
|
12210
|
+
const i18nContext = createI18nContextOp(I18nContextKind.Attr, job.allocateXrefId(), null, op.i18nMessage, null);
|
|
12211
|
+
unit.create.push(i18nContext);
|
|
12212
|
+
attrContextByMessage.set(op.i18nMessage, i18nContext.xref);
|
|
12213
|
+
}
|
|
12214
|
+
op.i18nContext = attrContextByMessage.get(op.i18nMessage);
|
|
12215
|
+
break;
|
|
12216
|
+
}
|
|
12217
|
+
}
|
|
12218
|
+
}
|
|
12219
|
+
// Create i18n context ops for root i18n blocks.
|
|
12220
|
+
const blockContextByI18nBlock = new Map();
|
|
12115
12221
|
for (const unit of job.units) {
|
|
12116
12222
|
for (const op of unit.create) {
|
|
12117
12223
|
switch (op.kind) {
|
|
12118
12224
|
case OpKind.I18nStart:
|
|
12119
|
-
currentI18nOp = op;
|
|
12120
|
-
// Each root i18n block gets its own context, child ones refer to the context for their
|
|
12121
|
-
// root block.
|
|
12122
12225
|
if (op.xref === op.root) {
|
|
12123
|
-
|
|
12124
|
-
unit.create.push(
|
|
12125
|
-
op.context = xref;
|
|
12126
|
-
|
|
12226
|
+
const contextOp = createI18nContextOp(I18nContextKind.RootI18n, job.allocateXrefId(), op.xref, op.message, null);
|
|
12227
|
+
unit.create.push(contextOp);
|
|
12228
|
+
op.context = contextOp.xref;
|
|
12229
|
+
blockContextByI18nBlock.set(op.xref, contextOp);
|
|
12127
12230
|
}
|
|
12128
12231
|
break;
|
|
12232
|
+
}
|
|
12233
|
+
}
|
|
12234
|
+
}
|
|
12235
|
+
// Assign i18n contexts for child i18n blocks. These don't need their own conext, instead they
|
|
12236
|
+
// should inherit from their root i18n block.
|
|
12237
|
+
for (const unit of job.units) {
|
|
12238
|
+
for (const op of unit.create) {
|
|
12239
|
+
if (op.kind === OpKind.I18nStart && op.xref !== op.root) {
|
|
12240
|
+
const rootContext = blockContextByI18nBlock.get(op.root);
|
|
12241
|
+
if (rootContext === undefined) {
|
|
12242
|
+
throw Error('AssertionError: Root i18n block i18n context should have been created.');
|
|
12243
|
+
}
|
|
12244
|
+
op.context = rootContext.xref;
|
|
12245
|
+
blockContextByI18nBlock.set(op.xref, rootContext);
|
|
12246
|
+
}
|
|
12247
|
+
}
|
|
12248
|
+
}
|
|
12249
|
+
// Create or assign i18n contexts for ICUs.
|
|
12250
|
+
let currentI18nOp = null;
|
|
12251
|
+
for (const unit of job.units) {
|
|
12252
|
+
for (const op of unit.create) {
|
|
12253
|
+
switch (op.kind) {
|
|
12254
|
+
case OpKind.I18nStart:
|
|
12255
|
+
currentI18nOp = op;
|
|
12256
|
+
break;
|
|
12129
12257
|
case OpKind.I18nEnd:
|
|
12130
12258
|
currentI18nOp = null;
|
|
12131
12259
|
break;
|
|
12132
12260
|
case OpKind.IcuStart:
|
|
12133
|
-
// If an ICU represents a different message than its containing block, we give it its own
|
|
12134
|
-
// i18n context.
|
|
12135
12261
|
if (currentI18nOp === null) {
|
|
12136
|
-
throw Error('Unexpected ICU outside of an i18n block.');
|
|
12262
|
+
throw Error('AssertionError: Unexpected ICU outside of an i18n block.');
|
|
12137
12263
|
}
|
|
12138
12264
|
if (op.message.id !== currentI18nOp.message.id) {
|
|
12139
|
-
//
|
|
12140
|
-
|
|
12141
|
-
|
|
12142
|
-
|
|
12265
|
+
// This ICU is a sub-message inside its parent i18n block message. We need to give it
|
|
12266
|
+
// its own context.
|
|
12267
|
+
const contextOp = createI18nContextOp(I18nContextKind.Icu, job.allocateXrefId(), currentI18nOp.xref, op.message, null);
|
|
12268
|
+
unit.create.push(contextOp);
|
|
12269
|
+
op.context = contextOp.xref;
|
|
12143
12270
|
}
|
|
12144
12271
|
else {
|
|
12145
|
-
//
|
|
12146
|
-
// the
|
|
12272
|
+
// This ICU is the only translatable content in its parent i18n block. We need to
|
|
12273
|
+
// convert the parent's context into an ICU context.
|
|
12147
12274
|
op.context = currentI18nOp.context;
|
|
12275
|
+
blockContextByI18nBlock.get(currentI18nOp.xref).contextKind = I18nContextKind.Icu;
|
|
12148
12276
|
}
|
|
12149
12277
|
break;
|
|
12150
12278
|
}
|
|
12151
12279
|
}
|
|
12152
|
-
for (const op of unit.ops()) {
|
|
12153
|
-
switch (op.kind) {
|
|
12154
|
-
case OpKind.Binding:
|
|
12155
|
-
case OpKind.Property:
|
|
12156
|
-
case OpKind.Attribute:
|
|
12157
|
-
case OpKind.ExtractedAttribute:
|
|
12158
|
-
if (!op.i18nMessage) {
|
|
12159
|
-
continue;
|
|
12160
|
-
}
|
|
12161
|
-
if (!messageToContext.has(op.i18nMessage)) {
|
|
12162
|
-
// create the context
|
|
12163
|
-
const i18nContext = job.allocateXrefId();
|
|
12164
|
-
unit.create.push(createI18nContextOp(I18nContextKind.Attr, i18nContext, null, op.i18nMessage, null));
|
|
12165
|
-
messageToContext.set(op.i18nMessage, i18nContext);
|
|
12166
|
-
}
|
|
12167
|
-
op.i18nContext = messageToContext.get(op.i18nMessage);
|
|
12168
|
-
break;
|
|
12169
|
-
}
|
|
12170
|
-
}
|
|
12171
12280
|
}
|
|
12172
|
-
|
|
12173
|
-
|
|
12281
|
+
}
|
|
12282
|
+
|
|
12283
|
+
/**
|
|
12284
|
+
* Deduplicate text bindings, e.g. <div class="cls1" class="cls2">
|
|
12285
|
+
*/
|
|
12286
|
+
function deduplicateTextBindings(job) {
|
|
12287
|
+
const seen = new Map();
|
|
12174
12288
|
for (const unit of job.units) {
|
|
12175
|
-
for (const op of unit.
|
|
12176
|
-
if (op.kind === OpKind.
|
|
12177
|
-
|
|
12289
|
+
for (const op of unit.update.reversed()) {
|
|
12290
|
+
if (op.kind === OpKind.Binding && op.isTextAttribute) {
|
|
12291
|
+
const seenForElement = seen.get(op.target) || new Set();
|
|
12292
|
+
if (seenForElement.has(op.name)) {
|
|
12293
|
+
if (job.compatibility === CompatibilityMode.TemplateDefinitionBuilder) {
|
|
12294
|
+
// For most duplicated attributes, TemplateDefinitionBuilder lists all of the values in
|
|
12295
|
+
// the consts array. However, for style and class attributes it only keeps the last one.
|
|
12296
|
+
// We replicate that behavior here since it has actual consequences for apps with
|
|
12297
|
+
// duplicate class or style attrs.
|
|
12298
|
+
if (op.name === 'style' || op.name === 'class') {
|
|
12299
|
+
OpList.remove(op);
|
|
12300
|
+
}
|
|
12301
|
+
}
|
|
12302
|
+
else {
|
|
12303
|
+
// TODO: Determine the correct behavior. It would probably make sense to merge multiple
|
|
12304
|
+
// style and class attributes. Alternatively we could just throw an error, as HTML
|
|
12305
|
+
// doesn't permit duplicate attributes.
|
|
12306
|
+
}
|
|
12307
|
+
}
|
|
12308
|
+
seenForElement.add(op.name);
|
|
12309
|
+
seen.set(op.target, seenForElement);
|
|
12178
12310
|
}
|
|
12179
12311
|
}
|
|
12180
12312
|
}
|
|
@@ -12560,13 +12692,18 @@ const LIST_DELIMITER = '|';
|
|
|
12560
12692
|
* used in the final output.
|
|
12561
12693
|
*/
|
|
12562
12694
|
function extractI18nMessages(job) {
|
|
12563
|
-
//
|
|
12564
|
-
|
|
12695
|
+
// Create an i18n message for each context.
|
|
12696
|
+
// TODO: Merge the context op with the message op since they're 1:1 anyways.
|
|
12697
|
+
const i18nMessagesByContext = new Map();
|
|
12565
12698
|
const i18nBlocks = new Map();
|
|
12699
|
+
const i18nContexts = new Map();
|
|
12566
12700
|
for (const unit of job.units) {
|
|
12567
12701
|
for (const op of unit.create) {
|
|
12568
12702
|
switch (op.kind) {
|
|
12569
12703
|
case OpKind.I18nContext:
|
|
12704
|
+
const i18nMessageOp = createI18nMessage(job, op);
|
|
12705
|
+
unit.create.push(i18nMessageOp);
|
|
12706
|
+
i18nMessagesByContext.set(op.xref, i18nMessageOp);
|
|
12570
12707
|
i18nContexts.set(op.xref, op);
|
|
12571
12708
|
break;
|
|
12572
12709
|
case OpKind.I18nStart:
|
|
@@ -12575,54 +12712,47 @@ function extractI18nMessages(job) {
|
|
|
12575
12712
|
}
|
|
12576
12713
|
}
|
|
12577
12714
|
}
|
|
12578
|
-
//
|
|
12579
|
-
//
|
|
12580
|
-
|
|
12581
|
-
for (const unit of job.units) {
|
|
12582
|
-
for (const op of unit.create) {
|
|
12583
|
-
if (op.kind !== OpKind.I18nContext || op.contextKind !== I18nContextKind.Attr) {
|
|
12584
|
-
continue;
|
|
12585
|
-
}
|
|
12586
|
-
const i18nMessageOp = createI18nMessage(job, op);
|
|
12587
|
-
unit.create.push(i18nMessageOp);
|
|
12588
|
-
}
|
|
12589
|
-
}
|
|
12590
|
-
// Extract messages from root i18n blocks.
|
|
12591
|
-
const i18nBlockMessages = new Map();
|
|
12592
|
-
for (const unit of job.units) {
|
|
12593
|
-
for (const op of unit.create) {
|
|
12594
|
-
if (op.kind === OpKind.I18nStart && op.xref === op.root) {
|
|
12595
|
-
if (!op.context) {
|
|
12596
|
-
throw Error('I18n start op should have its context set.');
|
|
12597
|
-
}
|
|
12598
|
-
const i18nMessageOp = createI18nMessage(job, i18nContexts.get(op.context));
|
|
12599
|
-
i18nBlockMessages.set(op.xref, i18nMessageOp);
|
|
12600
|
-
unit.create.push(i18nMessageOp);
|
|
12601
|
-
}
|
|
12602
|
-
}
|
|
12603
|
-
}
|
|
12604
|
-
// Extract messages from ICUs with their own sub-context.
|
|
12715
|
+
// Associate sub-messages for ICUs with their root message. At this point we can also remove the
|
|
12716
|
+
// ICU start/end ops, as they are no longer needed.
|
|
12717
|
+
let currentIcu = null;
|
|
12605
12718
|
for (const unit of job.units) {
|
|
12606
12719
|
for (const op of unit.create) {
|
|
12607
12720
|
switch (op.kind) {
|
|
12608
12721
|
case OpKind.IcuStart:
|
|
12609
|
-
|
|
12610
|
-
|
|
12722
|
+
currentIcu = op;
|
|
12723
|
+
OpList.remove(op);
|
|
12724
|
+
// Skip any contexts not associated with an ICU.
|
|
12725
|
+
const icuContext = i18nContexts.get(op.context);
|
|
12726
|
+
if (icuContext.contextKind !== I18nContextKind.Icu) {
|
|
12727
|
+
continue;
|
|
12611
12728
|
}
|
|
12612
|
-
|
|
12613
|
-
|
|
12614
|
-
|
|
12615
|
-
|
|
12616
|
-
|
|
12617
|
-
const subMessage = createI18nMessage(job, i18nContext, op.messagePlaceholder);
|
|
12618
|
-
unit.create.push(subMessage);
|
|
12619
|
-
const rootI18nId = i18nBlocks.get(i18nContext.i18nBlock).root;
|
|
12620
|
-
const parentMessage = i18nBlockMessages.get(rootI18nId);
|
|
12621
|
-
parentMessage?.subMessages.push(subMessage.xref);
|
|
12729
|
+
// Skip ICUs that share a context with their i18n message. These represent root-level
|
|
12730
|
+
// ICUs, not sub-messages.
|
|
12731
|
+
const i18nBlock = i18nBlocks.get(icuContext.i18nBlock);
|
|
12732
|
+
if (i18nBlock.context === icuContext.xref) {
|
|
12733
|
+
continue;
|
|
12622
12734
|
}
|
|
12623
|
-
|
|
12735
|
+
// Find the root message and push this ICUs message as a sub-message.
|
|
12736
|
+
const rootI18nBlock = i18nBlocks.get(i18nBlock.root);
|
|
12737
|
+
const rootMessage = i18nMessagesByContext.get(rootI18nBlock.context);
|
|
12738
|
+
if (rootMessage === undefined) {
|
|
12739
|
+
throw Error('AssertionError: ICU sub-message should belong to a root message.');
|
|
12740
|
+
}
|
|
12741
|
+
const subMessage = i18nMessagesByContext.get(icuContext.xref);
|
|
12742
|
+
subMessage.messagePlaceholder = op.messagePlaceholder;
|
|
12743
|
+
rootMessage.subMessages.push(subMessage.xref);
|
|
12624
12744
|
break;
|
|
12625
12745
|
case OpKind.IcuEnd:
|
|
12746
|
+
currentIcu = null;
|
|
12747
|
+
OpList.remove(op);
|
|
12748
|
+
break;
|
|
12749
|
+
case OpKind.IcuPlaceholder:
|
|
12750
|
+
// Add ICU placeholders to the message, then remove the ICU placeholder ops.
|
|
12751
|
+
if (currentIcu === null || currentIcu.context == null) {
|
|
12752
|
+
throw Error('AssertionError: Unexpected ICU placeholder outside of i18n context');
|
|
12753
|
+
}
|
|
12754
|
+
const msg = i18nMessagesByContext.get(currentIcu.context);
|
|
12755
|
+
msg.postprocessingParams.set(op.name, literal(formatIcuPlaceholder(op)));
|
|
12626
12756
|
OpList.remove(op);
|
|
12627
12757
|
break;
|
|
12628
12758
|
}
|
|
@@ -12635,14 +12765,19 @@ function extractI18nMessages(job) {
|
|
|
12635
12765
|
function createI18nMessage(job, context, messagePlaceholder) {
|
|
12636
12766
|
let formattedParams = formatParams(context.params);
|
|
12637
12767
|
const formattedPostprocessingParams = formatParams(context.postprocessingParams);
|
|
12638
|
-
let needsPostprocessing =
|
|
12639
|
-
for (const values of context.params.values()) {
|
|
12640
|
-
if (values.length > 1) {
|
|
12641
|
-
needsPostprocessing = true;
|
|
12642
|
-
}
|
|
12643
|
-
}
|
|
12768
|
+
let needsPostprocessing = [...context.params.values()].some(v => v.length > 1);
|
|
12644
12769
|
return createI18nMessageOp(job.allocateXrefId(), context.xref, context.i18nBlock, context.message, messagePlaceholder ?? null, formattedParams, formattedPostprocessingParams, needsPostprocessing);
|
|
12645
12770
|
}
|
|
12771
|
+
/**
|
|
12772
|
+
* Formats an ICU placeholder into a single string with expression placeholders.
|
|
12773
|
+
*/
|
|
12774
|
+
function formatIcuPlaceholder(op) {
|
|
12775
|
+
if (op.strings.length !== op.expressionPlaceholders.length + 1) {
|
|
12776
|
+
throw Error(`AsserionError: Invalid ICU placeholder with ${op.strings.length} strings and ${op.expressionPlaceholders.length} expressions`);
|
|
12777
|
+
}
|
|
12778
|
+
const values = op.expressionPlaceholders.map(formatValue);
|
|
12779
|
+
return op.strings.flatMap((str, i) => [str, values[i] || '']).join('');
|
|
12780
|
+
}
|
|
12646
12781
|
/**
|
|
12647
12782
|
* Formats a map of `I18nParamValue[]` values into a map of `Expression` values.
|
|
12648
12783
|
*/
|
|
@@ -12981,7 +13116,7 @@ const BANG_IMPORTANT = '!important';
|
|
|
12981
13116
|
*/
|
|
12982
13117
|
function parseHostStyleProperties(job) {
|
|
12983
13118
|
for (const op of job.root.update) {
|
|
12984
|
-
if (op.kind
|
|
13119
|
+
if (!(op.kind === OpKind.Binding && op.bindingKind === BindingKind.Property)) {
|
|
12985
13120
|
continue;
|
|
12986
13121
|
}
|
|
12987
13122
|
if (op.name.endsWith(BANG_IMPORTANT)) {
|
|
@@ -20139,7 +20274,7 @@ function collectMessage(job, fileBasedI18nSuffix, messages, messageOp) {
|
|
|
20139
20274
|
let transformFn = undefined;
|
|
20140
20275
|
// If nescessary, add a post-processing step and resolve any placeholder params that are
|
|
20141
20276
|
// set in post-processing.
|
|
20142
|
-
if (messageOp.needsPostprocessing) {
|
|
20277
|
+
if (messageOp.needsPostprocessing || messageOp.postprocessingParams.size > 0) {
|
|
20143
20278
|
// Sort the post-processing params for consistency with TemaplateDefinitionBuilder output.
|
|
20144
20279
|
const postprocessingParams = Object.fromEntries([...messageOp.postprocessingParams.entries()].sort());
|
|
20145
20280
|
const formattedPostprocessingParams = formatI18nPlaceholderNamesInMap(postprocessingParams, /* useCamelCase */ false);
|
|
@@ -20169,7 +20304,6 @@ function addSubMessageParams(messageOp, subMessagePlaceholders) {
|
|
|
20169
20304
|
else {
|
|
20170
20305
|
messageOp.params.set(placeholder, literal(`${ESCAPE}${I18N_ICU_MAPPING_PREFIX}${placeholder}${ESCAPE}`));
|
|
20171
20306
|
messageOp.postprocessingParams.set(placeholder, literalArr(subMessages));
|
|
20172
|
-
messageOp.needsPostprocessing = true;
|
|
20173
20307
|
}
|
|
20174
20308
|
}
|
|
20175
20309
|
}
|
|
@@ -20255,6 +20389,7 @@ function convertI18nText(job) {
|
|
|
20255
20389
|
let currentIcu = null;
|
|
20256
20390
|
const textNodeI18nBlocks = new Map();
|
|
20257
20391
|
const textNodeIcus = new Map();
|
|
20392
|
+
const icuPlaceholderByText = new Map();
|
|
20258
20393
|
for (const op of unit.create) {
|
|
20259
20394
|
switch (op.kind) {
|
|
20260
20395
|
case OpKind.I18nStart:
|
|
@@ -20279,7 +20414,19 @@ function convertI18nText(job) {
|
|
|
20279
20414
|
if (currentI18n !== null) {
|
|
20280
20415
|
textNodeI18nBlocks.set(op.xref, currentI18n);
|
|
20281
20416
|
textNodeIcus.set(op.xref, currentIcu);
|
|
20282
|
-
|
|
20417
|
+
if (op.icuPlaceholder !== null) {
|
|
20418
|
+
// Create an op to represent the ICU placeholder. Initially set its static text to the
|
|
20419
|
+
// value of the text op, though this may be overwritten later if this text op is a
|
|
20420
|
+
// placeholder for an interpolation.
|
|
20421
|
+
const icuPlaceholderOp = createIcuPlaceholderOp(job.allocateXrefId(), op.icuPlaceholder, [op.initialValue]);
|
|
20422
|
+
OpList.replace(op, icuPlaceholderOp);
|
|
20423
|
+
icuPlaceholderByText.set(op.xref, icuPlaceholderOp);
|
|
20424
|
+
}
|
|
20425
|
+
else {
|
|
20426
|
+
// Otherwise just remove the text op, since its value is already accounted for in the
|
|
20427
|
+
// translated message.
|
|
20428
|
+
OpList.remove(op);
|
|
20429
|
+
}
|
|
20283
20430
|
}
|
|
20284
20431
|
break;
|
|
20285
20432
|
}
|
|
@@ -20294,6 +20441,7 @@ function convertI18nText(job) {
|
|
|
20294
20441
|
}
|
|
20295
20442
|
const i18nOp = textNodeI18nBlocks.get(op.target);
|
|
20296
20443
|
const icuOp = textNodeIcus.get(op.target);
|
|
20444
|
+
const icuPlaceholder = icuPlaceholderByText.get(op.target);
|
|
20297
20445
|
const contextId = icuOp ? icuOp.context : i18nOp.context;
|
|
20298
20446
|
const resolutionTime = icuOp ? I18nParamResolutionTime.Postproccessing :
|
|
20299
20447
|
I18nParamResolutionTime.Creation;
|
|
@@ -20302,9 +20450,14 @@ function convertI18nText(job) {
|
|
|
20302
20450
|
const expr = op.interpolation.expressions[i];
|
|
20303
20451
|
// For now, this i18nExpression depends on the slot context of the enclosing i18n block.
|
|
20304
20452
|
// Later, we will modify this, and advance to a different point.
|
|
20305
|
-
ops.push(createI18nExpressionOp(contextId, i18nOp.xref, i18nOp.xref, i18nOp.handle, expr, op.interpolation.i18nPlaceholders[i], resolutionTime, I18nExpressionFor.I18nText, '', expr.sourceSpan ?? op.sourceSpan));
|
|
20453
|
+
ops.push(createI18nExpressionOp(contextId, i18nOp.xref, i18nOp.xref, i18nOp.handle, expr, icuPlaceholder?.xref ?? null, op.interpolation.i18nPlaceholders[i] ?? null, resolutionTime, I18nExpressionFor.I18nText, '', expr.sourceSpan ?? op.sourceSpan));
|
|
20306
20454
|
}
|
|
20307
20455
|
OpList.replaceWithMany(op, ops);
|
|
20456
|
+
// If this interpolation is part of an ICU placeholder, add the strings and expressions to
|
|
20457
|
+
// the placeholder.
|
|
20458
|
+
if (icuPlaceholder !== undefined) {
|
|
20459
|
+
icuPlaceholder.strings = op.interpolation.strings;
|
|
20460
|
+
}
|
|
20308
20461
|
break;
|
|
20309
20462
|
}
|
|
20310
20463
|
}
|
|
@@ -20487,7 +20640,7 @@ function addNamesToView(unit, baseName, state, compatibility) {
|
|
|
20487
20640
|
op.handlerFnName = sanitizeIdentifier(op.handlerFnName);
|
|
20488
20641
|
break;
|
|
20489
20642
|
case OpKind.Variable:
|
|
20490
|
-
varNames.set(op.xref, getVariableName(op.variable, state));
|
|
20643
|
+
varNames.set(op.xref, getVariableName(unit, op.variable, state));
|
|
20491
20644
|
break;
|
|
20492
20645
|
case OpKind.RepeaterCreate:
|
|
20493
20646
|
if (!(unit instanceof ViewCompilationUnit)) {
|
|
@@ -20542,15 +20695,23 @@ function addNamesToView(unit, baseName, state, compatibility) {
|
|
|
20542
20695
|
});
|
|
20543
20696
|
}
|
|
20544
20697
|
}
|
|
20545
|
-
function getVariableName(variable, state) {
|
|
20698
|
+
function getVariableName(unit, variable, state) {
|
|
20546
20699
|
if (variable.name === null) {
|
|
20547
20700
|
switch (variable.kind) {
|
|
20548
20701
|
case SemanticVariableKind.Context:
|
|
20549
20702
|
variable.name = `ctx_r${state.index++}`;
|
|
20550
20703
|
break;
|
|
20551
20704
|
case SemanticVariableKind.Identifier:
|
|
20552
|
-
|
|
20553
|
-
|
|
20705
|
+
if (unit.job.compatibility === CompatibilityMode.TemplateDefinitionBuilder) {
|
|
20706
|
+
// TODO: Prefix increment and `_r` are for compatiblity with the old naming scheme.
|
|
20707
|
+
// This has the potential to cause collisions when `ctx` is the identifier, so we need a
|
|
20708
|
+
// special check for that as well.
|
|
20709
|
+
const compatPrefix = variable.identifier === 'ctx' ? 'i' : '';
|
|
20710
|
+
variable.name = `${variable.identifier}_${compatPrefix}r${++state.index}`;
|
|
20711
|
+
}
|
|
20712
|
+
else {
|
|
20713
|
+
variable.name = `${variable.identifier}_i${state.index++}`;
|
|
20714
|
+
}
|
|
20554
20715
|
break;
|
|
20555
20716
|
default:
|
|
20556
20717
|
// TODO: Prefix increment for compatibility only.
|
|
@@ -20747,17 +20908,27 @@ const CREATE_ORDERING = [
|
|
|
20747
20908
|
* op kinds.
|
|
20748
20909
|
*/
|
|
20749
20910
|
const UPDATE_ORDERING = [
|
|
20750
|
-
{ test: kindWithInterpolationTest(OpKind.HostProperty, true) },
|
|
20751
|
-
{ test: kindWithInterpolationTest(OpKind.HostProperty, false) },
|
|
20752
20911
|
{ test: kindTest(OpKind.StyleMap), transform: keepLast },
|
|
20753
20912
|
{ test: kindTest(OpKind.ClassMap), transform: keepLast },
|
|
20754
20913
|
{ test: kindTest(OpKind.StyleProp) },
|
|
20755
20914
|
{ test: kindTest(OpKind.ClassProp) },
|
|
20756
|
-
{ test: kindWithInterpolationTest(OpKind.Property, true) },
|
|
20757
20915
|
{ test: kindWithInterpolationTest(OpKind.Attribute, true) },
|
|
20916
|
+
{ test: kindWithInterpolationTest(OpKind.Property, true) },
|
|
20758
20917
|
{ test: kindWithInterpolationTest(OpKind.Property, false) },
|
|
20759
20918
|
{ test: kindWithInterpolationTest(OpKind.Attribute, false) },
|
|
20760
20919
|
];
|
|
20920
|
+
/**
|
|
20921
|
+
* Host bindings have their own update ordering.
|
|
20922
|
+
*/
|
|
20923
|
+
const UPDATE_HOST_ORDERING = [
|
|
20924
|
+
{ test: kindWithInterpolationTest(OpKind.HostProperty, true) },
|
|
20925
|
+
{ test: kindWithInterpolationTest(OpKind.HostProperty, false) },
|
|
20926
|
+
{ test: kindTest(OpKind.Attribute) },
|
|
20927
|
+
{ test: kindTest(OpKind.StyleMap), transform: keepLast },
|
|
20928
|
+
{ test: kindTest(OpKind.ClassMap), transform: keepLast },
|
|
20929
|
+
{ test: kindTest(OpKind.StyleProp) },
|
|
20930
|
+
{ test: kindTest(OpKind.ClassProp) },
|
|
20931
|
+
];
|
|
20761
20932
|
/**
|
|
20762
20933
|
* The set of all op kinds we handle in the reordering phase.
|
|
20763
20934
|
*/
|
|
@@ -20778,7 +20949,8 @@ function orderOps(job) {
|
|
|
20778
20949
|
// Create mode:
|
|
20779
20950
|
orderWithin(unit.create, CREATE_ORDERING);
|
|
20780
20951
|
// Update mode:
|
|
20781
|
-
|
|
20952
|
+
const ordering = unit.job.kind === CompilationJobKind.Host ? UPDATE_HOST_ORDERING : UPDATE_ORDERING;
|
|
20953
|
+
orderWithin(unit.update, ordering);
|
|
20782
20954
|
}
|
|
20783
20955
|
}
|
|
20784
20956
|
/**
|
|
@@ -20833,10 +21005,28 @@ function keepLast(ops) {
|
|
|
20833
21005
|
* class property.
|
|
20834
21006
|
*/
|
|
20835
21007
|
function parseExtractedStyles(job) {
|
|
21008
|
+
const elements = new Map();
|
|
21009
|
+
for (const unit of job.units) {
|
|
21010
|
+
for (const op of unit.create) {
|
|
21011
|
+
if (isElementOrContainerOp(op)) {
|
|
21012
|
+
elements.set(op.xref, op);
|
|
21013
|
+
}
|
|
21014
|
+
}
|
|
21015
|
+
}
|
|
20836
21016
|
for (const unit of job.units) {
|
|
20837
21017
|
for (const op of unit.create) {
|
|
20838
21018
|
if (op.kind === OpKind.ExtractedAttribute && op.bindingKind === BindingKind.Attribute &&
|
|
20839
21019
|
isStringLiteral(op.expression)) {
|
|
21020
|
+
const target = elements.get(op.target);
|
|
21021
|
+
if (target !== undefined && target.kind === OpKind.Template &&
|
|
21022
|
+
target.templateKind === TemplateKind.Structural) {
|
|
21023
|
+
// TemplateDefinitionBuilder will not apply class and style bindings to structural
|
|
21024
|
+
// directives; instead, it will leave them as attributes.
|
|
21025
|
+
// (It's not clear what that would mean, anyway -- classes and styles on a structural
|
|
21026
|
+
// element should probably be a parse error.)
|
|
21027
|
+
// TODO: We may be able to remove this once Template Pipeline is the default.
|
|
21028
|
+
continue;
|
|
21029
|
+
}
|
|
20840
21030
|
if (op.name === 'style') {
|
|
20841
21031
|
const parsedStyles = parse(op.expression.value);
|
|
20842
21032
|
for (let i = 0; i < parsedStyles.length - 1; i += 2) {
|
|
@@ -20871,15 +21061,6 @@ function removeContentSelectors(job) {
|
|
|
20871
21061
|
OpList.remove(op);
|
|
20872
21062
|
}
|
|
20873
21063
|
break;
|
|
20874
|
-
case OpKind.Projection:
|
|
20875
|
-
// op.attributes is an array of [attr1-name, attr1-value, attr2-name, attr2-value, ...],
|
|
20876
|
-
// find the "select" attribute and remove its name and corresponding value.
|
|
20877
|
-
for (let i = op.attributes.length - 2; i >= 0; i -= 2) {
|
|
20878
|
-
if (isSelectAttribute(op.attributes[i])) {
|
|
20879
|
-
op.attributes.splice(i, 2);
|
|
20880
|
-
}
|
|
20881
|
-
}
|
|
20882
|
-
break;
|
|
20883
21064
|
}
|
|
20884
21065
|
}
|
|
20885
21066
|
}
|
|
@@ -21051,8 +21232,10 @@ function wrapTemplateWithI18n(unit, parentI18n) {
|
|
|
21051
21232
|
// Only add i18n ops if they have not already been propagated to this template.
|
|
21052
21233
|
if (unit.create.head.next?.kind !== OpKind.I18nStart) {
|
|
21053
21234
|
const id = unit.job.allocateXrefId();
|
|
21054
|
-
OpList.insertAfter(
|
|
21055
|
-
|
|
21235
|
+
OpList.insertAfter(
|
|
21236
|
+
// Nested ng-template i18n start/end ops should not recieve source spans.
|
|
21237
|
+
createI18nStartOp(id, parentI18n.message, parentI18n.root, null), unit.create.head);
|
|
21238
|
+
OpList.insertBefore(createI18nEndOp(id, null), unit.create.tail);
|
|
21056
21239
|
}
|
|
21057
21240
|
}
|
|
21058
21241
|
|
|
@@ -21313,22 +21496,22 @@ function projectionDef(def) {
|
|
|
21313
21496
|
}
|
|
21314
21497
|
function projection(slot, projectionSlotIndex, attributes, sourceSpan) {
|
|
21315
21498
|
const args = [literal(slot)];
|
|
21316
|
-
if (projectionSlotIndex !== 0 || attributes
|
|
21499
|
+
if (projectionSlotIndex !== 0 || attributes !== null) {
|
|
21317
21500
|
args.push(literal(projectionSlotIndex));
|
|
21318
|
-
if (attributes
|
|
21319
|
-
args.push(
|
|
21501
|
+
if (attributes !== null) {
|
|
21502
|
+
args.push(attributes);
|
|
21320
21503
|
}
|
|
21321
21504
|
}
|
|
21322
21505
|
return call(Identifiers.projection, args, sourceSpan);
|
|
21323
21506
|
}
|
|
21324
|
-
function i18nStart(slot, constIndex, subTemplateIndex) {
|
|
21507
|
+
function i18nStart(slot, constIndex, subTemplateIndex, sourceSpan) {
|
|
21325
21508
|
const args = [literal(slot), literal(constIndex)];
|
|
21326
21509
|
if (subTemplateIndex !== null) {
|
|
21327
21510
|
args.push(literal(subTemplateIndex));
|
|
21328
21511
|
}
|
|
21329
|
-
return call(Identifiers.i18nStart, args,
|
|
21512
|
+
return call(Identifiers.i18nStart, args, sourceSpan);
|
|
21330
21513
|
}
|
|
21331
|
-
function repeaterCreate(slot, viewFnName, decls, vars, tag, constIndex, trackByFn, trackByUsesComponentInstance, emptyViewFnName, emptyDecls, emptyVars, sourceSpan) {
|
|
21514
|
+
function repeaterCreate(slot, viewFnName, decls, vars, tag, constIndex, trackByFn, trackByUsesComponentInstance, emptyViewFnName, emptyDecls, emptyVars, emptyTag, emptyConstIndex, sourceSpan) {
|
|
21332
21515
|
const args = [
|
|
21333
21516
|
literal(slot),
|
|
21334
21517
|
variable(viewFnName),
|
|
@@ -21342,6 +21525,12 @@ function repeaterCreate(slot, viewFnName, decls, vars, tag, constIndex, trackByF
|
|
|
21342
21525
|
args.push(literal(trackByUsesComponentInstance));
|
|
21343
21526
|
if (emptyViewFnName !== null) {
|
|
21344
21527
|
args.push(variable(emptyViewFnName), literal(emptyDecls), literal(emptyVars));
|
|
21528
|
+
if (emptyTag !== null || emptyConstIndex !== null) {
|
|
21529
|
+
args.push(literal(emptyTag));
|
|
21530
|
+
}
|
|
21531
|
+
if (emptyConstIndex !== null) {
|
|
21532
|
+
args.push(literal(emptyConstIndex));
|
|
21533
|
+
}
|
|
21345
21534
|
}
|
|
21346
21535
|
}
|
|
21347
21536
|
return call(Identifiers.repeaterCreate, args, sourceSpan);
|
|
@@ -21352,15 +21541,15 @@ function repeater(collection, sourceSpan) {
|
|
|
21352
21541
|
function deferWhen(prefetch, expr, sourceSpan) {
|
|
21353
21542
|
return call(prefetch ? Identifiers.deferPrefetchWhen : Identifiers.deferWhen, [expr], sourceSpan);
|
|
21354
21543
|
}
|
|
21355
|
-
function i18n(slot, constIndex, subTemplateIndex) {
|
|
21544
|
+
function i18n(slot, constIndex, subTemplateIndex, sourceSpan) {
|
|
21356
21545
|
const args = [literal(slot), literal(constIndex)];
|
|
21357
21546
|
if (subTemplateIndex) {
|
|
21358
21547
|
args.push(literal(subTemplateIndex));
|
|
21359
21548
|
}
|
|
21360
|
-
return call(Identifiers.i18n, args,
|
|
21549
|
+
return call(Identifiers.i18n, args, sourceSpan);
|
|
21361
21550
|
}
|
|
21362
|
-
function i18nEnd() {
|
|
21363
|
-
return call(Identifiers.i18nEnd, [],
|
|
21551
|
+
function i18nEnd(endSourceSpan) {
|
|
21552
|
+
return call(Identifiers.i18nEnd, [], endSourceSpan);
|
|
21364
21553
|
}
|
|
21365
21554
|
function i18nAttributes(slot, i18nAttributesConfig) {
|
|
21366
21555
|
const args = [literal(slot), literal(i18nAttributesConfig)];
|
|
@@ -21720,6 +21909,31 @@ function reify(job) {
|
|
|
21720
21909
|
reifyUpdateOperations(unit, unit.update);
|
|
21721
21910
|
}
|
|
21722
21911
|
}
|
|
21912
|
+
/**
|
|
21913
|
+
* This function can be used a sanity check -- it walks every expression in the const pool, and
|
|
21914
|
+
* every expression reachable from an op, and makes sure that there are no IR expressions
|
|
21915
|
+
* left. This is nice to use for debugging mysterious failures where an IR expression cannot be
|
|
21916
|
+
* output from the output AST code.
|
|
21917
|
+
*/
|
|
21918
|
+
function ensureNoIrForDebug(job) {
|
|
21919
|
+
for (const stmt of job.pool.statements) {
|
|
21920
|
+
transformExpressionsInStatement(stmt, expr => {
|
|
21921
|
+
if (isIrExpression(expr)) {
|
|
21922
|
+
throw new Error(`AssertionError: IR expression found during reify: ${ExpressionKind[expr.kind]}`);
|
|
21923
|
+
}
|
|
21924
|
+
return expr;
|
|
21925
|
+
}, VisitorContextFlag.None);
|
|
21926
|
+
}
|
|
21927
|
+
for (const unit of job.units) {
|
|
21928
|
+
for (const op of unit.ops()) {
|
|
21929
|
+
visitExpressionsInOp(op, expr => {
|
|
21930
|
+
if (isIrExpression(expr)) {
|
|
21931
|
+
throw new Error(`AssertionError: IR expression found during reify: ${ExpressionKind[expr.kind]}`);
|
|
21932
|
+
}
|
|
21933
|
+
});
|
|
21934
|
+
}
|
|
21935
|
+
}
|
|
21936
|
+
}
|
|
21723
21937
|
function reifyCreateOperations(unit, ops) {
|
|
21724
21938
|
for (const op of ops) {
|
|
21725
21939
|
transformExpressionsInOp(op, reifyIrExpression, VisitorContextFlag.None);
|
|
@@ -21728,31 +21942,31 @@ function reifyCreateOperations(unit, ops) {
|
|
|
21728
21942
|
OpList.replace(op, text(op.handle.slot, op.initialValue, op.sourceSpan));
|
|
21729
21943
|
break;
|
|
21730
21944
|
case OpKind.ElementStart:
|
|
21731
|
-
OpList.replace(op, elementStart(op.handle.slot, op.tag, op.attributes, op.localRefs, op.
|
|
21945
|
+
OpList.replace(op, elementStart(op.handle.slot, op.tag, op.attributes, op.localRefs, op.startSourceSpan));
|
|
21732
21946
|
break;
|
|
21733
21947
|
case OpKind.Element:
|
|
21734
|
-
OpList.replace(op, element(op.handle.slot, op.tag, op.attributes, op.localRefs, op.
|
|
21948
|
+
OpList.replace(op, element(op.handle.slot, op.tag, op.attributes, op.localRefs, op.wholeSourceSpan));
|
|
21735
21949
|
break;
|
|
21736
21950
|
case OpKind.ElementEnd:
|
|
21737
21951
|
OpList.replace(op, elementEnd(op.sourceSpan));
|
|
21738
21952
|
break;
|
|
21739
21953
|
case OpKind.ContainerStart:
|
|
21740
|
-
OpList.replace(op, elementContainerStart(op.handle.slot, op.attributes, op.localRefs, op.
|
|
21954
|
+
OpList.replace(op, elementContainerStart(op.handle.slot, op.attributes, op.localRefs, op.startSourceSpan));
|
|
21741
21955
|
break;
|
|
21742
21956
|
case OpKind.Container:
|
|
21743
|
-
OpList.replace(op, elementContainer(op.handle.slot, op.attributes, op.localRefs, op.
|
|
21957
|
+
OpList.replace(op, elementContainer(op.handle.slot, op.attributes, op.localRefs, op.wholeSourceSpan));
|
|
21744
21958
|
break;
|
|
21745
21959
|
case OpKind.ContainerEnd:
|
|
21746
21960
|
OpList.replace(op, elementContainerEnd());
|
|
21747
21961
|
break;
|
|
21748
21962
|
case OpKind.I18nStart:
|
|
21749
|
-
OpList.replace(op, i18nStart(op.handle.slot, op.messageIndex, op.subTemplateIndex));
|
|
21963
|
+
OpList.replace(op, i18nStart(op.handle.slot, op.messageIndex, op.subTemplateIndex, op.sourceSpan));
|
|
21750
21964
|
break;
|
|
21751
21965
|
case OpKind.I18nEnd:
|
|
21752
|
-
OpList.replace(op, i18nEnd());
|
|
21966
|
+
OpList.replace(op, i18nEnd(op.sourceSpan));
|
|
21753
21967
|
break;
|
|
21754
21968
|
case OpKind.I18n:
|
|
21755
|
-
OpList.replace(op, i18n(op.handle.slot, op.messageIndex, op.subTemplateIndex));
|
|
21969
|
+
OpList.replace(op, i18n(op.handle.slot, op.messageIndex, op.subTemplateIndex, op.sourceSpan));
|
|
21756
21970
|
break;
|
|
21757
21971
|
case OpKind.I18nAttributes:
|
|
21758
21972
|
if (op.i18nAttributesConfig === null) {
|
|
@@ -21768,7 +21982,7 @@ function reifyCreateOperations(unit, ops) {
|
|
|
21768
21982
|
throw new Error(`AssertionError: local refs array should have been extracted into a constant`);
|
|
21769
21983
|
}
|
|
21770
21984
|
const childView = unit.job.views.get(op.xref);
|
|
21771
|
-
OpList.replace(op, template(op.handle.slot, variable(childView.fnName), childView.decls, childView.vars, op.tag, op.attributes, op.localRefs, op.
|
|
21985
|
+
OpList.replace(op, template(op.handle.slot, variable(childView.fnName), childView.decls, childView.vars, op.tag, op.attributes, op.localRefs, op.startSourceSpan));
|
|
21772
21986
|
break;
|
|
21773
21987
|
case OpKind.DisableBindings:
|
|
21774
21988
|
OpList.replace(op, disableBindings());
|
|
@@ -21783,7 +21997,7 @@ function reifyCreateOperations(unit, ops) {
|
|
|
21783
21997
|
const listenerFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, op.consumesDollarEvent);
|
|
21784
21998
|
const eventTargetResolver = op.eventTarget ? GLOBAL_TARGET_RESOLVERS$1.get(op.eventTarget) : null;
|
|
21785
21999
|
if (eventTargetResolver === undefined) {
|
|
21786
|
-
throw new Error(`
|
|
22000
|
+
throw new Error(`Unexpected global target '${op.eventTarget}' defined for '${op.name}' event. Supported list of global targets: window,document,body.`);
|
|
21787
22001
|
}
|
|
21788
22002
|
OpList.replace(op, listener(op.name, listenerFn, eventTargetResolver, op.hostListener && op.isAnimationListener, op.sourceSpan));
|
|
21789
22003
|
break;
|
|
@@ -21870,7 +22084,7 @@ function reifyCreateOperations(unit, ops) {
|
|
|
21870
22084
|
emptyDecls = emptyView.decls;
|
|
21871
22085
|
emptyVars = emptyView.vars;
|
|
21872
22086
|
}
|
|
21873
|
-
OpList.replace(op, repeaterCreate(op.handle.slot, repeaterView.fnName, op.decls, op.vars, op.tag, op.attributes, op.trackByFn, op.usesComponentInstance, emptyViewFnName, emptyDecls, emptyVars, op.
|
|
22087
|
+
OpList.replace(op, repeaterCreate(op.handle.slot, repeaterView.fnName, op.decls, op.vars, op.tag, op.attributes, op.trackByFn, op.usesComponentInstance, emptyViewFnName, emptyDecls, emptyVars, op.emptyTag, op.emptyAttributes, op.wholeSourceSpan));
|
|
21874
22088
|
break;
|
|
21875
22089
|
case OpKind.Statement:
|
|
21876
22090
|
// Pass statement operations directly through.
|
|
@@ -22500,6 +22714,7 @@ function resolveI18nExpressionPlaceholders(job) {
|
|
|
22500
22714
|
// Record all of the i18n context ops, and the sub-template index for each i18n op.
|
|
22501
22715
|
const subTemplateIndicies = new Map();
|
|
22502
22716
|
const i18nContexts = new Map();
|
|
22717
|
+
const icuPlaceholders = new Map();
|
|
22503
22718
|
for (const unit of job.units) {
|
|
22504
22719
|
for (const op of unit.create) {
|
|
22505
22720
|
switch (op.kind) {
|
|
@@ -22509,6 +22724,9 @@ function resolveI18nExpressionPlaceholders(job) {
|
|
|
22509
22724
|
case OpKind.I18nContext:
|
|
22510
22725
|
i18nContexts.set(op.xref, op);
|
|
22511
22726
|
break;
|
|
22727
|
+
case OpKind.IcuPlaceholder:
|
|
22728
|
+
icuPlaceholders.set(op.xref, op);
|
|
22729
|
+
break;
|
|
22512
22730
|
}
|
|
22513
22731
|
}
|
|
22514
22732
|
}
|
|
@@ -22522,76 +22740,32 @@ function resolveI18nExpressionPlaceholders(job) {
|
|
|
22522
22740
|
for (const unit of job.units) {
|
|
22523
22741
|
for (const op of unit.update) {
|
|
22524
22742
|
if (op.kind === OpKind.I18nExpression) {
|
|
22525
|
-
const i18nContext = i18nContexts.get(op.context);
|
|
22526
22743
|
const index = expressionIndices.get(referenceIndex(op)) || 0;
|
|
22527
22744
|
const subTemplateIndex = subTemplateIndicies.get(op.i18nOwner) ?? null;
|
|
22528
|
-
|
|
22529
|
-
const params = op.resolutionTime === I18nParamResolutionTime.Creation ?
|
|
22530
|
-
i18nContext.params :
|
|
22531
|
-
i18nContext.postprocessingParams;
|
|
22532
|
-
const values = params.get(op.i18nPlaceholder) || [];
|
|
22533
|
-
values.push({
|
|
22745
|
+
const value = {
|
|
22534
22746
|
value: index,
|
|
22535
22747
|
subTemplateIndex: subTemplateIndex,
|
|
22536
22748
|
flags: I18nParamValueFlags.ExpressionIndex
|
|
22537
|
-
}
|
|
22538
|
-
|
|
22749
|
+
};
|
|
22750
|
+
updatePlaceholder(op, value, i18nContexts, icuPlaceholders);
|
|
22539
22751
|
expressionIndices.set(referenceIndex(op), index + 1);
|
|
22540
22752
|
}
|
|
22541
22753
|
}
|
|
22542
22754
|
}
|
|
22543
22755
|
}
|
|
22544
|
-
|
|
22545
|
-
|
|
22546
|
-
|
|
22547
|
-
|
|
22548
|
-
|
|
22549
|
-
|
|
22550
|
-
|
|
22551
|
-
|
|
22552
|
-
|
|
22553
|
-
node.visit(new ResolveIcuPlaceholdersVisitor(op.postprocessingParams));
|
|
22554
|
-
}
|
|
22555
|
-
}
|
|
22556
|
-
}
|
|
22557
|
-
}
|
|
22558
|
-
}
|
|
22559
|
-
/**
|
|
22560
|
-
* Visitor for i18n AST that resolves ICU params into the given map.
|
|
22561
|
-
*/
|
|
22562
|
-
class ResolveIcuPlaceholdersVisitor extends RecurseVisitor {
|
|
22563
|
-
constructor(params) {
|
|
22564
|
-
super();
|
|
22565
|
-
this.params = params;
|
|
22756
|
+
function updatePlaceholder(op, value, i18nContexts, icuPlaceholders) {
|
|
22757
|
+
if (op.i18nPlaceholder !== null) {
|
|
22758
|
+
const i18nContext = i18nContexts.get(op.context);
|
|
22759
|
+
const params = op.resolutionTime === I18nParamResolutionTime.Creation ?
|
|
22760
|
+
i18nContext.params :
|
|
22761
|
+
i18nContext.postprocessingParams;
|
|
22762
|
+
const values = params.get(op.i18nPlaceholder) || [];
|
|
22763
|
+
values.push(value);
|
|
22764
|
+
params.set(op.i18nPlaceholder, values);
|
|
22566
22765
|
}
|
|
22567
|
-
|
|
22568
|
-
|
|
22569
|
-
|
|
22570
|
-
// block's context as part of the `resolveI18nElementPlaceholders` phase.
|
|
22571
|
-
if (placeholder.startName && placeholder.startSourceSpan &&
|
|
22572
|
-
!this.params.has(placeholder.startName)) {
|
|
22573
|
-
this.params.set(placeholder.startName, [{
|
|
22574
|
-
value: placeholder.startSourceSpan?.toString(),
|
|
22575
|
-
subTemplateIndex: null,
|
|
22576
|
-
flags: I18nParamValueFlags.None
|
|
22577
|
-
}]);
|
|
22578
|
-
}
|
|
22579
|
-
if (placeholder.closeName && placeholder.endSourceSpan &&
|
|
22580
|
-
!this.params.has(placeholder.closeName)) {
|
|
22581
|
-
this.params.set(placeholder.closeName, [{
|
|
22582
|
-
value: placeholder.endSourceSpan?.toString(),
|
|
22583
|
-
subTemplateIndex: null,
|
|
22584
|
-
flags: I18nParamValueFlags.None
|
|
22585
|
-
}]);
|
|
22586
|
-
}
|
|
22587
|
-
}
|
|
22588
|
-
visitTagPlaceholder(placeholder) {
|
|
22589
|
-
super.visitTagPlaceholder(placeholder);
|
|
22590
|
-
this.visitContainerPlaceholder(placeholder);
|
|
22591
|
-
}
|
|
22592
|
-
visitBlockPlaceholder(placeholder) {
|
|
22593
|
-
super.visitBlockPlaceholder(placeholder);
|
|
22594
|
-
this.visitContainerPlaceholder(placeholder);
|
|
22766
|
+
if (op.icuPlaceholder !== null) {
|
|
22767
|
+
const icuPlaceholderOp = icuPlaceholders.get(op.icuPlaceholder);
|
|
22768
|
+
icuPlaceholderOp?.expressionPlaceholders.push(value);
|
|
22595
22769
|
}
|
|
22596
22770
|
}
|
|
22597
22771
|
|
|
@@ -23043,6 +23217,9 @@ function generateTrackFns(job) {
|
|
|
23043
23217
|
// Find all component context reads.
|
|
23044
23218
|
let usesComponentContext = false;
|
|
23045
23219
|
op.track = transformExpressionsInExpression(op.track, expr => {
|
|
23220
|
+
if (expr instanceof PipeBindingExpr || expr instanceof PipeBindingVariadicExpr) {
|
|
23221
|
+
throw new Error(`Illegal State: Pipes are not allowed in this context`);
|
|
23222
|
+
}
|
|
23046
23223
|
if (expr instanceof TrackContextExpr) {
|
|
23047
23224
|
usesComponentContext = true;
|
|
23048
23225
|
return variable('this');
|
|
@@ -23266,7 +23443,14 @@ function varsUsedByOp(op) {
|
|
|
23266
23443
|
return op.interpolation.expressions.length;
|
|
23267
23444
|
case OpKind.I18nExpression:
|
|
23268
23445
|
case OpKind.Conditional:
|
|
23446
|
+
case OpKind.DeferWhen:
|
|
23269
23447
|
return 1;
|
|
23448
|
+
case OpKind.RepeaterCreate:
|
|
23449
|
+
// Repeaters may require an extra variable binding slot, if they have an empty view, for the
|
|
23450
|
+
// empty block tracking.
|
|
23451
|
+
// TODO: It's a bit odd to have a create mode instruction consume variable slots. Maybe we can
|
|
23452
|
+
// find a way to use the Repeater update op instead.
|
|
23453
|
+
return op.emptyView ? 1 : 0;
|
|
23270
23454
|
default:
|
|
23271
23455
|
throw new Error(`Unhandled op: ${OpKind[op.kind]}`);
|
|
23272
23456
|
}
|
|
@@ -23722,12 +23906,13 @@ function wrapI18nIcus(job) {
|
|
|
23722
23906
|
case OpKind.IcuStart:
|
|
23723
23907
|
if (currentI18nOp === null) {
|
|
23724
23908
|
addedI18nId = job.allocateXrefId();
|
|
23725
|
-
|
|
23909
|
+
// ICU i18n start/end ops should not recieve source spans.
|
|
23910
|
+
OpList.insertBefore(createI18nStartOp(addedI18nId, op.message, undefined, null), op);
|
|
23726
23911
|
}
|
|
23727
23912
|
break;
|
|
23728
23913
|
case OpKind.IcuEnd:
|
|
23729
23914
|
if (addedI18nId !== null) {
|
|
23730
|
-
OpList.insertAfter(createI18nEndOp(addedI18nId), op);
|
|
23915
|
+
OpList.insertAfter(createI18nEndOp(addedI18nId, null), op);
|
|
23731
23916
|
addedI18nId = null;
|
|
23732
23917
|
}
|
|
23733
23918
|
break;
|
|
@@ -23750,6 +23935,7 @@ const phases = [
|
|
|
23750
23935
|
{ kind: CompilationJobKind.Tmpl, fn: emitNamespaceChanges },
|
|
23751
23936
|
{ kind: CompilationJobKind.Tmpl, fn: propagateI18nBlocks },
|
|
23752
23937
|
{ kind: CompilationJobKind.Tmpl, fn: wrapI18nIcus },
|
|
23938
|
+
{ kind: CompilationJobKind.Both, fn: deduplicateTextBindings },
|
|
23753
23939
|
{ kind: CompilationJobKind.Both, fn: specializeStyleBindings },
|
|
23754
23940
|
{ kind: CompilationJobKind.Both, fn: specializeBindings },
|
|
23755
23941
|
{ kind: CompilationJobKind.Both, fn: extractAttributes },
|
|
@@ -23788,7 +23974,6 @@ const phases = [
|
|
|
23788
23974
|
{ kind: CompilationJobKind.Tmpl, fn: createDeferDepsFns },
|
|
23789
23975
|
{ kind: CompilationJobKind.Tmpl, fn: resolveI18nElementPlaceholders },
|
|
23790
23976
|
{ kind: CompilationJobKind.Tmpl, fn: resolveI18nExpressionPlaceholders },
|
|
23791
|
-
{ kind: CompilationJobKind.Tmpl, fn: resolveI18nIcuPlaceholders },
|
|
23792
23977
|
{ kind: CompilationJobKind.Tmpl, fn: extractI18nMessages },
|
|
23793
23978
|
{ kind: CompilationJobKind.Tmpl, fn: generateTrackFns },
|
|
23794
23979
|
{ kind: CompilationJobKind.Tmpl, fn: collectI18nConsts },
|
|
@@ -23948,7 +24133,7 @@ function ingestHostBinding(input, bindingParser, constantPool) {
|
|
|
23948
24133
|
const securityContexts = bindingParser
|
|
23949
24134
|
.calcPossibleSecurityContexts(input.componentSelector, property.name, bindingKind === BindingKind.Attribute)
|
|
23950
24135
|
.filter(context => context !== SecurityContext.NONE);
|
|
23951
|
-
ingestHostProperty(job, property, bindingKind,
|
|
24136
|
+
ingestHostProperty(job, property, bindingKind, securityContexts);
|
|
23952
24137
|
}
|
|
23953
24138
|
for (const [name, expr] of Object.entries(input.attributes) ?? []) {
|
|
23954
24139
|
const securityContexts = bindingParser.calcPossibleSecurityContexts(input.componentSelector, name, true)
|
|
@@ -23962,7 +24147,7 @@ function ingestHostBinding(input, bindingParser, constantPool) {
|
|
|
23962
24147
|
}
|
|
23963
24148
|
// TODO: We should refactor the parser to use the same types and structures for host bindings as
|
|
23964
24149
|
// with ordinary components. This would allow us to share a lot more ingestion code.
|
|
23965
|
-
function ingestHostProperty(job, property, bindingKind,
|
|
24150
|
+
function ingestHostProperty(job, property, bindingKind, securityContexts) {
|
|
23966
24151
|
let expression;
|
|
23967
24152
|
const ast = property.expression.ast;
|
|
23968
24153
|
if (ast instanceof Interpolation$1) {
|
|
@@ -23971,20 +24156,21 @@ function ingestHostProperty(job, property, bindingKind, isTextAttribute, securit
|
|
|
23971
24156
|
else {
|
|
23972
24157
|
expression = convertAst(ast, job, property.sourceSpan);
|
|
23973
24158
|
}
|
|
23974
|
-
job.root.update.push(createBindingOp(job.root.xref, bindingKind, property.name, expression, null, securityContexts,
|
|
24159
|
+
job.root.update.push(createBindingOp(job.root.xref, bindingKind, property.name, expression, null, securityContexts, false, false, null, /* TODO: How do Host bindings handle i18n attrs? */ null, property.sourceSpan));
|
|
23975
24160
|
}
|
|
23976
24161
|
function ingestHostAttribute(job, name, value, securityContexts) {
|
|
23977
|
-
const attrBinding = createBindingOp(job.root.xref, BindingKind.Attribute, name, value, null, securityContexts,
|
|
24162
|
+
const attrBinding = createBindingOp(job.root.xref, BindingKind.Attribute, name, value, null, securityContexts,
|
|
24163
|
+
/* Host attributes should always be extracted to const hostAttrs, even if they are not
|
|
24164
|
+
*strictly* text literals */
|
|
24165
|
+
true, false, null,
|
|
23978
24166
|
/* TODO */ null,
|
|
23979
|
-
|
|
24167
|
+
/** TODO: May be null? */ value.sourceSpan);
|
|
23980
24168
|
job.root.update.push(attrBinding);
|
|
23981
24169
|
}
|
|
23982
24170
|
function ingestHostEvent(job, event) {
|
|
23983
24171
|
const [phase, target] = event.type === 0 /* e.ParsedEventType.Regular */ ? [null, event.targetOrPhase] :
|
|
23984
24172
|
[event.targetOrPhase, null];
|
|
23985
|
-
const eventBinding = createListenerOp(job.root.xref, new SlotHandle(), event.name, null,
|
|
23986
|
-
// TODO: Can this be a chain?
|
|
23987
|
-
eventBinding.handlerOps.push(createStatementOp(new ReturnStatement(convertAst(event.handler.ast, job, event.sourceSpan), event.handlerSpan)));
|
|
24173
|
+
const eventBinding = createListenerOp(job.root.xref, new SlotHandle(), event.name, null, makeListenerHandlerOps(job.root, event.handler, event.handlerSpan), phase, target, true, event.sourceSpan);
|
|
23988
24174
|
job.root.create.push(eventBinding);
|
|
23989
24175
|
}
|
|
23990
24176
|
/**
|
|
@@ -24002,10 +24188,10 @@ function ingestNodes(unit, template) {
|
|
|
24002
24188
|
ingestContent(unit, node);
|
|
24003
24189
|
}
|
|
24004
24190
|
else if (node instanceof Text$3) {
|
|
24005
|
-
ingestText(unit, node);
|
|
24191
|
+
ingestText(unit, node, null);
|
|
24006
24192
|
}
|
|
24007
24193
|
else if (node instanceof BoundText) {
|
|
24008
|
-
ingestBoundText(unit, node);
|
|
24194
|
+
ingestBoundText(unit, node, null);
|
|
24009
24195
|
}
|
|
24010
24196
|
else if (node instanceof IfBlock) {
|
|
24011
24197
|
ingestIfBlock(unit, node);
|
|
@@ -24037,7 +24223,7 @@ function ingestElement(unit, element) {
|
|
|
24037
24223
|
}
|
|
24038
24224
|
const id = unit.job.allocateXrefId();
|
|
24039
24225
|
const [namespaceKey, elementName] = splitNsName(element.name);
|
|
24040
|
-
const startOp = createElementStartOp(elementName, id, namespaceForKey(namespaceKey), element.i18n instanceof TagPlaceholder ? element.i18n : undefined, element.startSourceSpan);
|
|
24226
|
+
const startOp = createElementStartOp(elementName, id, namespaceForKey(namespaceKey), element.i18n instanceof TagPlaceholder ? element.i18n : undefined, element.startSourceSpan, element.sourceSpan);
|
|
24041
24227
|
unit.create.push(startOp);
|
|
24042
24228
|
ingestElementBindings(unit, startOp, element);
|
|
24043
24229
|
ingestReferences(startOp, element);
|
|
@@ -24045,7 +24231,7 @@ function ingestElement(unit, element) {
|
|
|
24045
24231
|
let i18nBlockId = null;
|
|
24046
24232
|
if (element.i18n instanceof Message) {
|
|
24047
24233
|
i18nBlockId = unit.job.allocateXrefId();
|
|
24048
|
-
unit.create.push(createI18nStartOp(i18nBlockId, element.i18n));
|
|
24234
|
+
unit.create.push(createI18nStartOp(i18nBlockId, element.i18n, undefined, element.startSourceSpan));
|
|
24049
24235
|
}
|
|
24050
24236
|
ingestNodes(unit, element.children);
|
|
24051
24237
|
// The source span for the end op is typically the element closing tag. However, if no closing tag
|
|
@@ -24057,7 +24243,7 @@ function ingestElement(unit, element) {
|
|
|
24057
24243
|
unit.create.push(endOp);
|
|
24058
24244
|
// If there is an i18n message associated with this element, insert i18n start and end ops.
|
|
24059
24245
|
if (i18nBlockId !== null) {
|
|
24060
|
-
OpList.insertBefore(createI18nEndOp(i18nBlockId), endOp);
|
|
24246
|
+
OpList.insertBefore(createI18nEndOp(i18nBlockId, element.endSourceSpan ?? element.startSourceSpan), endOp);
|
|
24061
24247
|
}
|
|
24062
24248
|
}
|
|
24063
24249
|
/**
|
|
@@ -24080,7 +24266,7 @@ function ingestTemplate(unit, tmpl) {
|
|
|
24080
24266
|
'' :
|
|
24081
24267
|
prefixWithNamespace(tagNameWithoutNamespace, namespace);
|
|
24082
24268
|
const templateKind = isPlainTemplate(tmpl) ? TemplateKind.NgTemplate : TemplateKind.Structural;
|
|
24083
|
-
const templateOp = createTemplateOp(childView.xref, templateKind, tagNameWithoutNamespace, functionNameSuffix, namespace, i18nPlaceholder, tmpl.startSourceSpan);
|
|
24269
|
+
const templateOp = createTemplateOp(childView.xref, templateKind, tagNameWithoutNamespace, functionNameSuffix, namespace, i18nPlaceholder, tmpl.startSourceSpan, tmpl.sourceSpan);
|
|
24084
24270
|
unit.create.push(templateOp);
|
|
24085
24271
|
ingestTemplateBindings(unit, templateOp, tmpl, templateKind);
|
|
24086
24272
|
ingestReferences(templateOp, tmpl);
|
|
@@ -24093,8 +24279,8 @@ function ingestTemplate(unit, tmpl) {
|
|
|
24093
24279
|
// element/template the directive is placed on.
|
|
24094
24280
|
if (templateKind === TemplateKind.NgTemplate && tmpl.i18n instanceof Message) {
|
|
24095
24281
|
const id = unit.job.allocateXrefId();
|
|
24096
|
-
OpList.insertAfter(createI18nStartOp(id, tmpl.i18n), childView.create.head);
|
|
24097
|
-
OpList.insertBefore(createI18nEndOp(id), childView.create.tail);
|
|
24282
|
+
OpList.insertAfter(createI18nStartOp(id, tmpl.i18n, undefined, tmpl.startSourceSpan), childView.create.head);
|
|
24283
|
+
OpList.insertBefore(createI18nEndOp(id, tmpl.endSourceSpan ?? tmpl.startSourceSpan), childView.create.tail);
|
|
24098
24284
|
}
|
|
24099
24285
|
}
|
|
24100
24286
|
/**
|
|
@@ -24104,8 +24290,7 @@ function ingestContent(unit, content) {
|
|
|
24104
24290
|
if (content.i18n !== undefined && !(content.i18n instanceof TagPlaceholder)) {
|
|
24105
24291
|
throw Error(`Unhandled i18n metadata type for element: ${content.i18n.constructor.name}`);
|
|
24106
24292
|
}
|
|
24107
|
-
const
|
|
24108
|
-
const op = createProjectionOp(unit.job.allocateXrefId(), content.selector, content.i18n, attrs, content.sourceSpan);
|
|
24293
|
+
const op = createProjectionOp(unit.job.allocateXrefId(), content.selector, content.i18n, content.sourceSpan);
|
|
24109
24294
|
for (const attr of content.attributes) {
|
|
24110
24295
|
const securityContext = domSchema.securityContext(content.name, attr.name, true);
|
|
24111
24296
|
unit.update.push(createBindingOp(op.xref, BindingKind.Attribute, attr.name, literal(attr.value), null, securityContext, true, false, null, asMessage(attr.i18n), attr.sourceSpan));
|
|
@@ -24115,13 +24300,13 @@ function ingestContent(unit, content) {
|
|
|
24115
24300
|
/**
|
|
24116
24301
|
* Ingest a literal text node from the AST into the given `ViewCompilation`.
|
|
24117
24302
|
*/
|
|
24118
|
-
function ingestText(unit, text) {
|
|
24119
|
-
unit.create.push(createTextOp(unit.job.allocateXrefId(), text.value, text.sourceSpan));
|
|
24303
|
+
function ingestText(unit, text, icuPlaceholder) {
|
|
24304
|
+
unit.create.push(createTextOp(unit.job.allocateXrefId(), text.value, icuPlaceholder, text.sourceSpan));
|
|
24120
24305
|
}
|
|
24121
24306
|
/**
|
|
24122
24307
|
* Ingest an interpolated text node from the AST into the given `ViewCompilation`.
|
|
24123
24308
|
*/
|
|
24124
|
-
function ingestBoundText(unit, text,
|
|
24309
|
+
function ingestBoundText(unit, text, icuPlaceholder) {
|
|
24125
24310
|
let value = text.value;
|
|
24126
24311
|
if (value instanceof ASTWithSource) {
|
|
24127
24312
|
value = value.ast;
|
|
@@ -24132,19 +24317,16 @@ function ingestBoundText(unit, text, i18nPlaceholders) {
|
|
|
24132
24317
|
if (text.i18n !== undefined && !(text.i18n instanceof Container)) {
|
|
24133
24318
|
throw Error(`Unhandled i18n metadata type for text interpolation: ${text.i18n?.constructor.name}`);
|
|
24134
24319
|
}
|
|
24135
|
-
|
|
24136
|
-
|
|
24137
|
-
|
|
24138
|
-
|
|
24139
|
-
|
|
24140
|
-
.map(placeholder => placeholder.name) :
|
|
24141
|
-
[];
|
|
24142
|
-
}
|
|
24320
|
+
const i18nPlaceholders = text.i18n instanceof Container ?
|
|
24321
|
+
text.i18n.children
|
|
24322
|
+
.filter((node) => node instanceof Placeholder)
|
|
24323
|
+
.map(placeholder => placeholder.name) :
|
|
24324
|
+
[];
|
|
24143
24325
|
if (i18nPlaceholders.length > 0 && i18nPlaceholders.length !== value.expressions.length) {
|
|
24144
24326
|
throw Error(`Unexpected number of i18n placeholders (${value.expressions.length}) for BoundText with ${value.expressions.length} expressions`);
|
|
24145
24327
|
}
|
|
24146
24328
|
const textXref = unit.job.allocateXrefId();
|
|
24147
|
-
unit.create.push(createTextOp(textXref, '', text.sourceSpan));
|
|
24329
|
+
unit.create.push(createTextOp(textXref, '', icuPlaceholder, text.sourceSpan));
|
|
24148
24330
|
// TemplateDefinitionBuilder does not generate source maps for sub-expressions inside an
|
|
24149
24331
|
// interpolation. We copy that behavior in compatibility mode.
|
|
24150
24332
|
// TODO: is it actually correct to generate these extra maps in modern mode?
|
|
@@ -24177,7 +24359,7 @@ function ingestIfBlock(unit, ifBlock) {
|
|
|
24177
24359
|
}
|
|
24178
24360
|
ifCaseI18nMeta = ifCase.i18n;
|
|
24179
24361
|
}
|
|
24180
|
-
const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, tagName, 'Conditional', Namespace.HTML, ifCaseI18nMeta, ifCase.sourceSpan);
|
|
24362
|
+
const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, tagName, 'Conditional', Namespace.HTML, ifCaseI18nMeta, ifCase.startSourceSpan, ifCase.sourceSpan);
|
|
24181
24363
|
unit.create.push(templateOp);
|
|
24182
24364
|
if (firstXref === null) {
|
|
24183
24365
|
firstXref = cView.xref;
|
|
@@ -24207,7 +24389,7 @@ function ingestSwitchBlock(unit, switchBlock) {
|
|
|
24207
24389
|
}
|
|
24208
24390
|
switchCaseI18nMeta = switchCase.i18n;
|
|
24209
24391
|
}
|
|
24210
|
-
const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, null, 'Case', Namespace.HTML, switchCaseI18nMeta, switchCase.sourceSpan);
|
|
24392
|
+
const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, null, 'Case', Namespace.HTML, switchCaseI18nMeta, switchCase.startSourceSpan, switchCase.sourceSpan);
|
|
24211
24393
|
unit.create.push(templateOp);
|
|
24212
24394
|
if (firstXref === null) {
|
|
24213
24395
|
firstXref = cView.xref;
|
|
@@ -24232,7 +24414,7 @@ function ingestDeferView(unit, suffix, i18nMeta, children, sourceSpan) {
|
|
|
24232
24414
|
}
|
|
24233
24415
|
const secondaryView = unit.job.allocateView(unit.xref);
|
|
24234
24416
|
ingestNodes(secondaryView, children);
|
|
24235
|
-
const templateOp = createTemplateOp(secondaryView.xref, TemplateKind.Block, null, `Defer${suffix}`, Namespace.HTML, i18nMeta, sourceSpan);
|
|
24417
|
+
const templateOp = createTemplateOp(secondaryView.xref, TemplateKind.Block, null, `Defer${suffix}`, Namespace.HTML, i18nMeta, sourceSpan, sourceSpan);
|
|
24236
24418
|
unit.create.push(templateOp);
|
|
24237
24419
|
return templateOp;
|
|
24238
24420
|
}
|
|
@@ -24310,6 +24492,11 @@ function ingestDeferBlock(unit, deferBlock) {
|
|
|
24310
24492
|
deferOnOps.push(deferOnOp);
|
|
24311
24493
|
}
|
|
24312
24494
|
if (triggers.when !== undefined) {
|
|
24495
|
+
if (triggers.when.value instanceof Interpolation$1) {
|
|
24496
|
+
// TemplateDefinitionBuilder supports this case, but it's very strange to me. What would it
|
|
24497
|
+
// even mean?
|
|
24498
|
+
throw new Error(`Unexpected interpolation in defer block when trigger`);
|
|
24499
|
+
}
|
|
24313
24500
|
const deferOnOp = createDeferWhenOp(deferXref, convertAst(triggers.when.value, unit.job, triggers.when.sourceSpan), prefetch, triggers.when.sourceSpan);
|
|
24314
24501
|
deferWhenOps.push(deferOnOp);
|
|
24315
24502
|
}
|
|
@@ -24329,10 +24516,10 @@ function ingestIcu(unit, icu) {
|
|
|
24329
24516
|
unit.create.push(createIcuStartOp(xref, icu.i18n, icuFromI18nMessage(icu.i18n).name, null));
|
|
24330
24517
|
for (const [placeholder, text] of Object.entries({ ...icu.vars, ...icu.placeholders })) {
|
|
24331
24518
|
if (text instanceof BoundText) {
|
|
24332
|
-
ingestBoundText(unit, text,
|
|
24519
|
+
ingestBoundText(unit, text, placeholder);
|
|
24333
24520
|
}
|
|
24334
24521
|
else {
|
|
24335
|
-
ingestText(unit, text);
|
|
24522
|
+
ingestText(unit, text, placeholder);
|
|
24336
24523
|
}
|
|
24337
24524
|
}
|
|
24338
24525
|
unit.create.push(createIcuEndOp(xref));
|
|
@@ -24366,9 +24553,11 @@ function ingestForBlock(unit, forBlock) {
|
|
|
24366
24553
|
const track = convertAst(forBlock.trackBy, unit.job, sourceSpan);
|
|
24367
24554
|
ingestNodes(repeaterView, forBlock.children);
|
|
24368
24555
|
let emptyView = null;
|
|
24556
|
+
let emptyTagName = null;
|
|
24369
24557
|
if (forBlock.empty !== null) {
|
|
24370
24558
|
emptyView = unit.job.allocateView(unit.xref);
|
|
24371
24559
|
ingestNodes(emptyView, forBlock.empty.children);
|
|
24560
|
+
emptyTagName = ingestControlFlowInsertionPoint(unit, emptyView.xref, forBlock.empty);
|
|
24372
24561
|
}
|
|
24373
24562
|
const varNames = {
|
|
24374
24563
|
$index: forBlock.contextVariables.$index.name,
|
|
@@ -24389,7 +24578,7 @@ function ingestForBlock(unit, forBlock) {
|
|
|
24389
24578
|
const i18nPlaceholder = forBlock.i18n;
|
|
24390
24579
|
const emptyI18nPlaceholder = forBlock.empty?.i18n;
|
|
24391
24580
|
const tagName = ingestControlFlowInsertionPoint(unit, repeaterView.xref, forBlock);
|
|
24392
|
-
const repeaterCreate = createRepeaterCreateOp(repeaterView.xref, emptyView?.xref ?? null, tagName, track, varNames, i18nPlaceholder, emptyI18nPlaceholder, forBlock.sourceSpan);
|
|
24581
|
+
const repeaterCreate = createRepeaterCreateOp(repeaterView.xref, emptyView?.xref ?? null, tagName, track, varNames, emptyTagName, i18nPlaceholder, emptyI18nPlaceholder, forBlock.startSourceSpan, forBlock.sourceSpan);
|
|
24393
24582
|
unit.create.push(repeaterCreate);
|
|
24394
24583
|
const expression = convertAst(forBlock.expression, unit.job, convertSourceSpan(forBlock.expression.span, forBlock.sourceSpan));
|
|
24395
24584
|
const repeater = createRepeaterOp(repeaterCreate.xref, repeaterCreate.handle, expression, forBlock.sourceSpan);
|
|
@@ -24403,7 +24592,29 @@ function convertAst(ast, job, baseSourceSpan) {
|
|
|
24403
24592
|
return convertAst(ast.ast, job, baseSourceSpan);
|
|
24404
24593
|
}
|
|
24405
24594
|
else if (ast instanceof PropertyRead) {
|
|
24406
|
-
|
|
24595
|
+
const isThisReceiver = ast.receiver instanceof ThisReceiver;
|
|
24596
|
+
// Whether this is an implicit receiver, *excluding* explicit reads of `this`.
|
|
24597
|
+
const isImplicitReceiver = ast.receiver instanceof ImplicitReceiver && !(ast.receiver instanceof ThisReceiver);
|
|
24598
|
+
// Whether the name of the read is a node that should be never retain its explicit this
|
|
24599
|
+
// receiver.
|
|
24600
|
+
const isSpecialNode = ast.name === '$any' || ast.name === '$event';
|
|
24601
|
+
// TODO: The most sensible condition here would be simply `isImplicitReceiver`, to convert only
|
|
24602
|
+
// actual implicit `this` reads, and not explicit ones. However, TemplateDefinitionBuilder (and
|
|
24603
|
+
// the Typecheck block!) both have the same bug, in which they also consider explicit `this`
|
|
24604
|
+
// reads to be implicit. This causes problems when the explicit `this` read is inside a
|
|
24605
|
+
// template with a context that also provides the variable name being read:
|
|
24606
|
+
// ```
|
|
24607
|
+
// <ng-template let-a>{{this.a}}</ng-template>
|
|
24608
|
+
// ```
|
|
24609
|
+
// The whole point of the explicit `this` was to access the class property, but TDB and the
|
|
24610
|
+
// current TCB treat the read as implicit, and give you the context property instead!
|
|
24611
|
+
//
|
|
24612
|
+
// For now, we emulate this old behvaior by aggressively converting explicit reads to to
|
|
24613
|
+
// implicit reads, except for the special cases that TDB and the current TCB protect. However,
|
|
24614
|
+
// it would be an improvement to fix this.
|
|
24615
|
+
//
|
|
24616
|
+
// See also the corresponding comment for the TCB, in `type_check_block.ts`.
|
|
24617
|
+
if (isImplicitReceiver || (isThisReceiver && !isSpecialNode)) {
|
|
24407
24618
|
return new LexicalReadExpr(ast.name);
|
|
24408
24619
|
}
|
|
24409
24620
|
else {
|
|
@@ -24507,13 +24718,13 @@ function convertAst(ast, job, baseSourceSpan) {
|
|
|
24507
24718
|
throw new Error(`Unhandled expression type "${ast.constructor.name}" in file "${baseSourceSpan?.start.file.url}"`);
|
|
24508
24719
|
}
|
|
24509
24720
|
}
|
|
24510
|
-
function convertAstWithInterpolation(job, value, i18nMeta) {
|
|
24721
|
+
function convertAstWithInterpolation(job, value, i18nMeta, sourceSpan) {
|
|
24511
24722
|
let expression;
|
|
24512
24723
|
if (value instanceof Interpolation$1) {
|
|
24513
|
-
expression = new Interpolation(value.strings, value.expressions.map(e => convertAst(e, job, null)), Object.keys(asMessage(i18nMeta)?.placeholders ?? {}));
|
|
24724
|
+
expression = new Interpolation(value.strings, value.expressions.map(e => convertAst(e, job, sourceSpan ?? null)), Object.keys(asMessage(i18nMeta)?.placeholders ?? {}));
|
|
24514
24725
|
}
|
|
24515
24726
|
else if (value instanceof AST) {
|
|
24516
|
-
expression = convertAst(value, job, null);
|
|
24727
|
+
expression = convertAst(value, job, sourceSpan ?? null);
|
|
24517
24728
|
}
|
|
24518
24729
|
else {
|
|
24519
24730
|
expression = literal(value);
|
|
@@ -28705,7 +28916,12 @@ class TemplateDefinitionBuilder {
|
|
|
28705
28916
|
});
|
|
28706
28917
|
const { expression: trackByExpression, usesComponentInstance: trackByUsesComponentInstance } = this.createTrackByFunction(block);
|
|
28707
28918
|
let emptyData = null;
|
|
28919
|
+
let emptyTagName = null;
|
|
28920
|
+
let emptyAttrsExprs;
|
|
28708
28921
|
if (block.empty !== null) {
|
|
28922
|
+
const emptyInferred = this.inferProjectionDataFromInsertionPoint(block.empty);
|
|
28923
|
+
emptyTagName = emptyInferred.tagName;
|
|
28924
|
+
emptyAttrsExprs = emptyInferred.attrsExprs;
|
|
28709
28925
|
emptyData = this.prepareEmbeddedTemplateFn(block.empty.children, '_ForEmpty', undefined, block.empty.i18n);
|
|
28710
28926
|
// Allocate an extra slot for the empty block tracking.
|
|
28711
28927
|
this.allocateBindingSlots(null);
|
|
@@ -28723,13 +28939,13 @@ class TemplateDefinitionBuilder {
|
|
|
28723
28939
|
trackByExpression,
|
|
28724
28940
|
];
|
|
28725
28941
|
if (emptyData !== null) {
|
|
28726
|
-
params.push(literal(trackByUsesComponentInstance), variable(emptyData.name), literal(emptyData.getConstCount()), literal(emptyData.getVarCount()));
|
|
28942
|
+
params.push(literal(trackByUsesComponentInstance), variable(emptyData.name), literal(emptyData.getConstCount()), literal(emptyData.getVarCount()), literal(emptyTagName), this.addAttrsToConsts(emptyAttrsExprs || null));
|
|
28727
28943
|
}
|
|
28728
28944
|
else if (trackByUsesComponentInstance) {
|
|
28729
28945
|
// If the tracking function doesn't use the component instance, we can omit the flag.
|
|
28730
28946
|
params.push(literal(trackByUsesComponentInstance));
|
|
28731
28947
|
}
|
|
28732
|
-
return params;
|
|
28948
|
+
return trimTrailingNulls(params);
|
|
28733
28949
|
});
|
|
28734
28950
|
// Note: the expression needs to be processed *after* the template,
|
|
28735
28951
|
// otherwise pipes injecting some symbols won't work (see #52102).
|
|
@@ -29488,12 +29704,16 @@ class BindingScope {
|
|
|
29488
29704
|
}
|
|
29489
29705
|
/** Binding scope of a `track` function inside a `for` loop block. */
|
|
29490
29706
|
class TrackByBindingScope extends BindingScope {
|
|
29491
|
-
constructor(parentScope,
|
|
29707
|
+
constructor(parentScope, globalOverrides) {
|
|
29492
29708
|
super(parentScope.bindingLevel + 1, parentScope);
|
|
29493
|
-
this.
|
|
29709
|
+
this.globalOverrides = globalOverrides;
|
|
29494
29710
|
this.componentAccessCount = 0;
|
|
29495
29711
|
}
|
|
29496
29712
|
get(name) {
|
|
29713
|
+
// Intercept any overridden globals.
|
|
29714
|
+
if (this.globalOverrides.hasOwnProperty(name)) {
|
|
29715
|
+
return variable(this.globalOverrides[name]);
|
|
29716
|
+
}
|
|
29497
29717
|
let current = this.parent;
|
|
29498
29718
|
// Prevent accesses of template variables outside the `for` loop.
|
|
29499
29719
|
while (current) {
|
|
@@ -29502,10 +29722,6 @@ class TrackByBindingScope extends BindingScope {
|
|
|
29502
29722
|
}
|
|
29503
29723
|
current = current.parent;
|
|
29504
29724
|
}
|
|
29505
|
-
// Intercept any aliased globals.
|
|
29506
|
-
if (this.globalAliases[name]) {
|
|
29507
|
-
return variable(this.globalAliases[name]);
|
|
29508
|
-
}
|
|
29509
29725
|
// When the component scope is accessed, we redirect it through `this`.
|
|
29510
29726
|
this.componentAccessCount++;
|
|
29511
29727
|
return variable('this').prop(name);
|
|
@@ -32046,7 +32262,7 @@ function publishFacade(global) {
|
|
|
32046
32262
|
* @description
|
|
32047
32263
|
* Entry point for all public APIs of the compiler package.
|
|
32048
32264
|
*/
|
|
32049
|
-
const VERSION = new Version('17.1.0-next.
|
|
32265
|
+
const VERSION = new Version('17.1.0-next.5');
|
|
32050
32266
|
|
|
32051
32267
|
class CompilerConfig {
|
|
32052
32268
|
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
@@ -33612,7 +33828,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$5 = '12.0.0';
|
|
|
33612
33828
|
function compileDeclareClassMetadata(metadata) {
|
|
33613
33829
|
const definitionMap = new DefinitionMap();
|
|
33614
33830
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
|
|
33615
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
33831
|
+
definitionMap.set('version', literal('17.1.0-next.5'));
|
|
33616
33832
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33617
33833
|
definitionMap.set('type', metadata.type);
|
|
33618
33834
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -33708,7 +33924,7 @@ function createDirectiveDefinitionMap(meta) {
|
|
|
33708
33924
|
const definitionMap = new DefinitionMap();
|
|
33709
33925
|
const minVersion = getMinimumVersionForPartialOutput(meta);
|
|
33710
33926
|
definitionMap.set('minVersion', literal(minVersion));
|
|
33711
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
33927
|
+
definitionMap.set('version', literal('17.1.0-next.5'));
|
|
33712
33928
|
// e.g. `type: MyDirective`
|
|
33713
33929
|
definitionMap.set('type', meta.type.value);
|
|
33714
33930
|
if (meta.isStandalone) {
|
|
@@ -34092,7 +34308,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
34092
34308
|
function compileDeclareFactoryFunction(meta) {
|
|
34093
34309
|
const definitionMap = new DefinitionMap();
|
|
34094
34310
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
34095
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
34311
|
+
definitionMap.set('version', literal('17.1.0-next.5'));
|
|
34096
34312
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
34097
34313
|
definitionMap.set('type', meta.type.value);
|
|
34098
34314
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -34127,7 +34343,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
34127
34343
|
function createInjectableDefinitionMap(meta) {
|
|
34128
34344
|
const definitionMap = new DefinitionMap();
|
|
34129
34345
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
34130
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
34346
|
+
definitionMap.set('version', literal('17.1.0-next.5'));
|
|
34131
34347
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
34132
34348
|
definitionMap.set('type', meta.type.value);
|
|
34133
34349
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -34178,7 +34394,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
34178
34394
|
function createInjectorDefinitionMap(meta) {
|
|
34179
34395
|
const definitionMap = new DefinitionMap();
|
|
34180
34396
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
34181
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
34397
|
+
definitionMap.set('version', literal('17.1.0-next.5'));
|
|
34182
34398
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
34183
34399
|
definitionMap.set('type', meta.type.value);
|
|
34184
34400
|
definitionMap.set('providers', meta.providers);
|
|
@@ -34211,7 +34427,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
34211
34427
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
34212
34428
|
}
|
|
34213
34429
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
34214
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
34430
|
+
definitionMap.set('version', literal('17.1.0-next.5'));
|
|
34215
34431
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
34216
34432
|
definitionMap.set('type', meta.type.value);
|
|
34217
34433
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -34262,7 +34478,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
34262
34478
|
function createPipeDefinitionMap(meta) {
|
|
34263
34479
|
const definitionMap = new DefinitionMap();
|
|
34264
34480
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
34265
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
34481
|
+
definitionMap.set('version', literal('17.1.0-next.5'));
|
|
34266
34482
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
34267
34483
|
// e.g. `type: MyPipe`
|
|
34268
34484
|
definitionMap.set('type', meta.type.value);
|