@angular/compiler 17.0.7 → 17.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/src/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 +7 -7
- package/esm2022/src/template/pipeline/ir/src/enums.mjs +7 -3
- package/esm2022/src/template/pipeline/ir/src/expression.mjs +5 -1
- package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +27 -9
- 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 +37 -34
- package/esm2022/src/template/pipeline/src/phases/attribute_extraction.mjs +5 -15
- package/esm2022/src/template/pipeline/src/phases/const_collection.mjs +25 -10
- 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/parse_extracted_styles.mjs +19 -1
- package/esm2022/src/template/pipeline/src/phases/reify.mjs +8 -8
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_expression_placeholders.mjs +23 -10
- package/esm2022/src/template/pipeline/src/phases/var_counting.mjs +8 -1
- package/esm2022/src/version.mjs +1 -1
- package/fesm2022/compiler.mjs +347 -253
- 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.0.
|
|
2
|
+
* @license Angular v17.0.8
|
|
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
|
}
|
|
@@ -3685,13 +3687,18 @@ var TagContentType;
|
|
|
3685
3687
|
TagContentType[TagContentType["ESCAPABLE_RAW_TEXT"] = 1] = "ESCAPABLE_RAW_TEXT";
|
|
3686
3688
|
TagContentType[TagContentType["PARSABLE_DATA"] = 2] = "PARSABLE_DATA";
|
|
3687
3689
|
})(TagContentType || (TagContentType = {}));
|
|
3688
|
-
function splitNsName(elementName) {
|
|
3690
|
+
function splitNsName(elementName, fatal = true) {
|
|
3689
3691
|
if (elementName[0] != ':') {
|
|
3690
3692
|
return [null, elementName];
|
|
3691
3693
|
}
|
|
3692
3694
|
const colonIndex = elementName.indexOf(':', 1);
|
|
3693
3695
|
if (colonIndex === -1) {
|
|
3694
|
-
|
|
3696
|
+
if (fatal) {
|
|
3697
|
+
throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
|
|
3698
|
+
}
|
|
3699
|
+
else {
|
|
3700
|
+
return [null, elementName];
|
|
3701
|
+
}
|
|
3695
3702
|
}
|
|
3696
3703
|
return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
|
|
3697
3704
|
}
|
|
@@ -8966,14 +8973,18 @@ var OpKind;
|
|
|
8966
8973
|
* An instruction to update an ICU expression.
|
|
8967
8974
|
*/
|
|
8968
8975
|
OpKind[OpKind["IcuEnd"] = 42] = "IcuEnd";
|
|
8976
|
+
/**
|
|
8977
|
+
* An instruction representing a placeholder in an ICU expression.
|
|
8978
|
+
*/
|
|
8979
|
+
OpKind[OpKind["IcuPlaceholder"] = 43] = "IcuPlaceholder";
|
|
8969
8980
|
/**
|
|
8970
8981
|
* An i18n context containing information needed to generate an i18n message.
|
|
8971
8982
|
*/
|
|
8972
|
-
OpKind[OpKind["I18nContext"] =
|
|
8983
|
+
OpKind[OpKind["I18nContext"] = 44] = "I18nContext";
|
|
8973
8984
|
/**
|
|
8974
8985
|
* A creation op that corresponds to i18n attributes on an element.
|
|
8975
8986
|
*/
|
|
8976
|
-
OpKind[OpKind["I18nAttributes"] =
|
|
8987
|
+
OpKind[OpKind["I18nAttributes"] = 45] = "I18nAttributes";
|
|
8977
8988
|
})(OpKind || (OpKind = {}));
|
|
8978
8989
|
/**
|
|
8979
8990
|
* Distinguishes different kinds of IR expressions.
|
|
@@ -9572,12 +9583,13 @@ function createDeferWhenOp(target, expr, prefetch, sourceSpan) {
|
|
|
9572
9583
|
sourceSpan,
|
|
9573
9584
|
...NEW_OP,
|
|
9574
9585
|
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9586
|
+
...TRAIT_CONSUMES_VARS,
|
|
9575
9587
|
};
|
|
9576
9588
|
}
|
|
9577
9589
|
/**
|
|
9578
9590
|
* Create an i18n expression op.
|
|
9579
9591
|
*/
|
|
9580
|
-
function createI18nExpressionOp(context, target, i18nOwner, handle, expression, i18nPlaceholder, resolutionTime, usage, name, sourceSpan) {
|
|
9592
|
+
function createI18nExpressionOp(context, target, i18nOwner, handle, expression, icuPlaceholder, i18nPlaceholder, resolutionTime, usage, name, sourceSpan) {
|
|
9581
9593
|
return {
|
|
9582
9594
|
kind: OpKind.I18nExpression,
|
|
9583
9595
|
context,
|
|
@@ -9585,6 +9597,7 @@ function createI18nExpressionOp(context, target, i18nOwner, handle, expression,
|
|
|
9585
9597
|
i18nOwner,
|
|
9586
9598
|
handle,
|
|
9587
9599
|
expression,
|
|
9600
|
+
icuPlaceholder,
|
|
9588
9601
|
i18nPlaceholder,
|
|
9589
9602
|
resolutionTime,
|
|
9590
9603
|
usage,
|
|
@@ -10354,6 +10367,9 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
10354
10367
|
op.placeholderConfig =
|
|
10355
10368
|
transformExpressionsInExpression(op.placeholderConfig, transform, flags);
|
|
10356
10369
|
}
|
|
10370
|
+
if (op.resolverFn !== null) {
|
|
10371
|
+
op.resolverFn = transformExpressionsInExpression(op.resolverFn, transform, flags);
|
|
10372
|
+
}
|
|
10357
10373
|
break;
|
|
10358
10374
|
case OpKind.I18nMessage:
|
|
10359
10375
|
for (const [placeholder, expr] of op.params) {
|
|
@@ -10390,6 +10406,7 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
10390
10406
|
case OpKind.Template:
|
|
10391
10407
|
case OpKind.Text:
|
|
10392
10408
|
case OpKind.I18nAttributes:
|
|
10409
|
+
case OpKind.IcuPlaceholder:
|
|
10393
10410
|
// These operations contain no expressions.
|
|
10394
10411
|
break;
|
|
10395
10412
|
default:
|
|
@@ -10797,7 +10814,7 @@ function isElementOrContainerOp(op) {
|
|
|
10797
10814
|
/**
|
|
10798
10815
|
* Create an `ElementStartOp`.
|
|
10799
10816
|
*/
|
|
10800
|
-
function createElementStartOp(tag, xref, namespace, i18nPlaceholder,
|
|
10817
|
+
function createElementStartOp(tag, xref, namespace, i18nPlaceholder, startSourceSpan, wholeSourceSpan) {
|
|
10801
10818
|
return {
|
|
10802
10819
|
kind: OpKind.ElementStart,
|
|
10803
10820
|
xref,
|
|
@@ -10808,7 +10825,8 @@ function createElementStartOp(tag, xref, namespace, i18nPlaceholder, sourceSpan)
|
|
|
10808
10825
|
nonBindable: false,
|
|
10809
10826
|
namespace,
|
|
10810
10827
|
i18nPlaceholder,
|
|
10811
|
-
|
|
10828
|
+
startSourceSpan,
|
|
10829
|
+
wholeSourceSpan,
|
|
10812
10830
|
...TRAIT_CONSUMES_SLOT,
|
|
10813
10831
|
...NEW_OP,
|
|
10814
10832
|
};
|
|
@@ -10816,7 +10834,7 @@ function createElementStartOp(tag, xref, namespace, i18nPlaceholder, sourceSpan)
|
|
|
10816
10834
|
/**
|
|
10817
10835
|
* Create a `TemplateOp`.
|
|
10818
10836
|
*/
|
|
10819
|
-
function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace, i18nPlaceholder,
|
|
10837
|
+
function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace, i18nPlaceholder, startSourceSpan, wholeSourceSpan) {
|
|
10820
10838
|
return {
|
|
10821
10839
|
kind: OpKind.Template,
|
|
10822
10840
|
xref,
|
|
@@ -10831,12 +10849,13 @@ function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace
|
|
|
10831
10849
|
nonBindable: false,
|
|
10832
10850
|
namespace,
|
|
10833
10851
|
i18nPlaceholder,
|
|
10834
|
-
|
|
10852
|
+
startSourceSpan,
|
|
10853
|
+
wholeSourceSpan,
|
|
10835
10854
|
...TRAIT_CONSUMES_SLOT,
|
|
10836
10855
|
...NEW_OP,
|
|
10837
10856
|
};
|
|
10838
10857
|
}
|
|
10839
|
-
function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, i18nPlaceholder, emptyI18nPlaceholder,
|
|
10858
|
+
function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, i18nPlaceholder, emptyI18nPlaceholder, startSourceSpan, wholeSourceSpan) {
|
|
10840
10859
|
return {
|
|
10841
10860
|
kind: OpKind.RepeaterCreate,
|
|
10842
10861
|
attributes: null,
|
|
@@ -10856,9 +10875,11 @@ function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, i1
|
|
|
10856
10875
|
usesComponentInstance: false,
|
|
10857
10876
|
i18nPlaceholder,
|
|
10858
10877
|
emptyI18nPlaceholder,
|
|
10859
|
-
|
|
10878
|
+
startSourceSpan,
|
|
10879
|
+
wholeSourceSpan,
|
|
10860
10880
|
...TRAIT_CONSUMES_SLOT,
|
|
10861
10881
|
...NEW_OP,
|
|
10882
|
+
...TRAIT_CONSUMES_VARS,
|
|
10862
10883
|
numSlotsUsed: emptyView === null ? 2 : 3,
|
|
10863
10884
|
};
|
|
10864
10885
|
}
|
|
@@ -10890,12 +10911,13 @@ function createEnableBindingsOp(xref) {
|
|
|
10890
10911
|
/**
|
|
10891
10912
|
* Create a `TextOp`.
|
|
10892
10913
|
*/
|
|
10893
|
-
function createTextOp(xref, initialValue, sourceSpan) {
|
|
10914
|
+
function createTextOp(xref, initialValue, icuPlaceholder, sourceSpan) {
|
|
10894
10915
|
return {
|
|
10895
10916
|
kind: OpKind.Text,
|
|
10896
10917
|
xref,
|
|
10897
10918
|
handle: new SlotHandle(),
|
|
10898
10919
|
initialValue,
|
|
10920
|
+
icuPlaceholder,
|
|
10899
10921
|
sourceSpan,
|
|
10900
10922
|
...TRAIT_CONSUMES_SLOT,
|
|
10901
10923
|
...NEW_OP,
|
|
@@ -11085,6 +11107,19 @@ function createIcuEndOp(xref) {
|
|
|
11085
11107
|
...NEW_OP,
|
|
11086
11108
|
};
|
|
11087
11109
|
}
|
|
11110
|
+
/**
|
|
11111
|
+
* Creates an ICU placeholder op.
|
|
11112
|
+
*/
|
|
11113
|
+
function createIcuPlaceholderOp(xref, name, strings) {
|
|
11114
|
+
return {
|
|
11115
|
+
kind: OpKind.IcuPlaceholder,
|
|
11116
|
+
xref,
|
|
11117
|
+
name,
|
|
11118
|
+
strings,
|
|
11119
|
+
expressionPlaceholders: [],
|
|
11120
|
+
...NEW_OP,
|
|
11121
|
+
};
|
|
11122
|
+
}
|
|
11088
11123
|
function createI18nContextOp(contextKind, xref, i18nBlock, message, sourceSpan) {
|
|
11089
11124
|
if (i18nBlock === null && contextKind !== I18nContextKind.Attr) {
|
|
11090
11125
|
throw new Error('AssertionError: i18nBlock must be provided for non-attribute contexts.');
|
|
@@ -11551,21 +11586,11 @@ function extractAttributeOp(unit, op, elements) {
|
|
|
11551
11586
|
if (op.expression instanceof Interpolation) {
|
|
11552
11587
|
return;
|
|
11553
11588
|
}
|
|
11554
|
-
let extractable = op.expression.isConstant();
|
|
11589
|
+
let extractable = op.isTextAttribute || op.expression.isConstant();
|
|
11555
11590
|
if (unit.job.compatibility === CompatibilityMode.TemplateDefinitionBuilder) {
|
|
11556
|
-
// TemplateDefinitionBuilder only
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
// For style and class attributes, TemplateDefinitionBuilder only extracted them if they were
|
|
11560
|
-
// text attributes. For example, `[attr.class]="'my-class'"` was not extracted despite being a
|
|
11561
|
-
// string literal, because it is not a text attribute.
|
|
11562
|
-
extractable &&= op.isTextAttribute;
|
|
11563
|
-
}
|
|
11564
|
-
if (unit.job.kind === CompilationJobKind.Host) {
|
|
11565
|
-
// TemplateDefinitionBuilder also does not seem to extract string literals if they are part of
|
|
11566
|
-
// a host attribute.
|
|
11567
|
-
extractable &&= op.isTextAttribute;
|
|
11568
|
-
}
|
|
11591
|
+
// TemplateDefinitionBuilder only extracts text attributes. It does not extract attriibute
|
|
11592
|
+
// bindings, even if they are constants.
|
|
11593
|
+
extractable &&= op.isTextAttribute;
|
|
11569
11594
|
}
|
|
11570
11595
|
if (extractable) {
|
|
11571
11596
|
const extractedAttributeOp = createExtractedAttributeOp(op.target, op.isStructuralTemplateAttribute ? BindingKind.Template : BindingKind.Attribute, op.name, op.expression, op.i18nContext, op.i18nMessage, op.securityContext);
|
|
@@ -11859,7 +11884,7 @@ function collectElementConsts(job) {
|
|
|
11859
11884
|
for (const unit of job.units) {
|
|
11860
11885
|
for (const op of unit.create) {
|
|
11861
11886
|
if (op.kind === OpKind.ExtractedAttribute) {
|
|
11862
|
-
const attributes = allElementAttributes.get(op.target) || new ElementAttributes();
|
|
11887
|
+
const attributes = allElementAttributes.get(op.target) || new ElementAttributes(job.compatibility);
|
|
11863
11888
|
allElementAttributes.set(op.target, attributes);
|
|
11864
11889
|
attributes.add(op.bindingKind, op.name, op.expression, op.trustedValueFn);
|
|
11865
11890
|
OpList.remove(op);
|
|
@@ -11904,11 +11929,6 @@ const FLYWEIGHT_ARRAY = Object.freeze([]);
|
|
|
11904
11929
|
* Container for all of the various kinds of attributes which are applied on an element.
|
|
11905
11930
|
*/
|
|
11906
11931
|
class ElementAttributes {
|
|
11907
|
-
constructor() {
|
|
11908
|
-
this.known = new Set();
|
|
11909
|
-
this.byKind = new Map;
|
|
11910
|
-
this.projectAs = null;
|
|
11911
|
-
}
|
|
11912
11932
|
get attributes() {
|
|
11913
11933
|
return this.byKind.get(BindingKind.Attribute) ?? FLYWEIGHT_ARRAY;
|
|
11914
11934
|
}
|
|
@@ -11927,11 +11947,31 @@ class ElementAttributes {
|
|
|
11927
11947
|
get i18n() {
|
|
11928
11948
|
return this.byKind.get(BindingKind.I18n) ?? FLYWEIGHT_ARRAY;
|
|
11929
11949
|
}
|
|
11950
|
+
constructor(compatibility) {
|
|
11951
|
+
this.compatibility = compatibility;
|
|
11952
|
+
this.known = new Map();
|
|
11953
|
+
this.byKind = new Map;
|
|
11954
|
+
this.projectAs = null;
|
|
11955
|
+
}
|
|
11956
|
+
isKnown(kind, name, value) {
|
|
11957
|
+
const nameToValue = this.known.get(kind) ?? new Set();
|
|
11958
|
+
this.known.set(kind, nameToValue);
|
|
11959
|
+
if (nameToValue.has(name)) {
|
|
11960
|
+
return true;
|
|
11961
|
+
}
|
|
11962
|
+
nameToValue.add(name);
|
|
11963
|
+
return false;
|
|
11964
|
+
}
|
|
11930
11965
|
add(kind, name, value, trustedValueFn) {
|
|
11931
|
-
|
|
11966
|
+
// TemplateDefinitionBuilder puts duplicate attribute, class, and style values into the consts
|
|
11967
|
+
// array. This seems inefficient, we can probably keep just the first one or the last value
|
|
11968
|
+
// (whichever actually gets applied when multiple values are listed for the same attribute).
|
|
11969
|
+
const allowDuplicates = this.compatibility === CompatibilityMode.TemplateDefinitionBuilder &&
|
|
11970
|
+
(kind === BindingKind.Attribute || kind === BindingKind.ClassName ||
|
|
11971
|
+
kind === BindingKind.StyleProperty);
|
|
11972
|
+
if (!allowDuplicates && this.isKnown(kind, name, value)) {
|
|
11932
11973
|
return;
|
|
11933
11974
|
}
|
|
11934
|
-
this.known.add(name);
|
|
11935
11975
|
// TODO: Can this be its own phase
|
|
11936
11976
|
if (name === 'ngProjectAs') {
|
|
11937
11977
|
if (value === null || !(value instanceof LiteralExpr) || (value.value == null) ||
|
|
@@ -11970,7 +12010,7 @@ class ElementAttributes {
|
|
|
11970
12010
|
* Gets an array of literal expressions representing the attribute's namespaced name.
|
|
11971
12011
|
*/
|
|
11972
12012
|
function getAttributeNameLiterals$1(name) {
|
|
11973
|
-
const [attributeNamespace, attributeName] = splitNsName(name);
|
|
12013
|
+
const [attributeNamespace, attributeName] = splitNsName(name, false);
|
|
11974
12014
|
const nameLiteral = literal(attributeName);
|
|
11975
12015
|
if (attributeNamespace) {
|
|
11976
12016
|
return [
|
|
@@ -12043,7 +12083,7 @@ function convertI18nBindings(job) {
|
|
|
12043
12083
|
if (op.expression.i18nPlaceholders.length !== op.expression.expressions.length) {
|
|
12044
12084
|
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`);
|
|
12045
12085
|
}
|
|
12046
|
-
ops.push(createI18nExpressionOp(op.i18nContext, i18nAttributesForElem.target, i18nAttributesForElem.xref, i18nAttributesForElem.handle, expr, op.expression.i18nPlaceholders[i], I18nParamResolutionTime.Creation, I18nExpressionFor.I18nAttribute, op.name, op.sourceSpan));
|
|
12086
|
+
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));
|
|
12047
12087
|
}
|
|
12048
12088
|
OpList.replaceWithMany(op, ops);
|
|
12049
12089
|
break;
|
|
@@ -12080,7 +12120,8 @@ function createDeferDepsFns(job) {
|
|
|
12080
12120
|
if (op.handle.slot === null) {
|
|
12081
12121
|
throw new Error('AssertionError: slot must be assigned bfore extracting defer deps functions');
|
|
12082
12122
|
}
|
|
12083
|
-
op.resolverFn = job.pool.getSharedFunctionReference(depsFnExpr, `${job.componentName}_Defer_${op.handle.slot}_DepsFn
|
|
12123
|
+
op.resolverFn = job.pool.getSharedFunctionReference(depsFnExpr, `${job.componentName}_Defer_${op.handle.slot}_DepsFn`,
|
|
12124
|
+
/* Don't use unique names for TDB compatibility */ false);
|
|
12084
12125
|
}
|
|
12085
12126
|
}
|
|
12086
12127
|
}
|
|
@@ -12097,75 +12138,119 @@ function createDeferDepsFns(job) {
|
|
|
12097
12138
|
* message.)
|
|
12098
12139
|
*/
|
|
12099
12140
|
function createI18nContexts(job) {
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
|
|
12141
|
+
// Create i18n context ops for i18n attrs.
|
|
12142
|
+
const attrContextByMessage = new Map();
|
|
12143
|
+
for (const unit of job.units) {
|
|
12144
|
+
for (const op of unit.ops()) {
|
|
12145
|
+
switch (op.kind) {
|
|
12146
|
+
case OpKind.Binding:
|
|
12147
|
+
case OpKind.Property:
|
|
12148
|
+
case OpKind.Attribute:
|
|
12149
|
+
case OpKind.ExtractedAttribute:
|
|
12150
|
+
if (op.i18nMessage === null) {
|
|
12151
|
+
continue;
|
|
12152
|
+
}
|
|
12153
|
+
if (!attrContextByMessage.has(op.i18nMessage)) {
|
|
12154
|
+
const i18nContext = createI18nContextOp(I18nContextKind.Attr, job.allocateXrefId(), null, op.i18nMessage, null);
|
|
12155
|
+
unit.create.push(i18nContext);
|
|
12156
|
+
attrContextByMessage.set(op.i18nMessage, i18nContext.xref);
|
|
12157
|
+
}
|
|
12158
|
+
op.i18nContext = attrContextByMessage.get(op.i18nMessage);
|
|
12159
|
+
break;
|
|
12160
|
+
}
|
|
12161
|
+
}
|
|
12162
|
+
}
|
|
12163
|
+
// Create i18n context ops for root i18n blocks.
|
|
12164
|
+
const blockContextByI18nBlock = new Map();
|
|
12106
12165
|
for (const unit of job.units) {
|
|
12107
12166
|
for (const op of unit.create) {
|
|
12108
12167
|
switch (op.kind) {
|
|
12109
12168
|
case OpKind.I18nStart:
|
|
12110
|
-
currentI18nOp = op;
|
|
12111
|
-
// Each root i18n block gets its own context, child ones refer to the context for their
|
|
12112
|
-
// root block.
|
|
12113
12169
|
if (op.xref === op.root) {
|
|
12114
|
-
|
|
12115
|
-
unit.create.push(
|
|
12116
|
-
op.context = xref;
|
|
12117
|
-
|
|
12170
|
+
const contextOp = createI18nContextOp(I18nContextKind.RootI18n, job.allocateXrefId(), op.xref, op.message, null);
|
|
12171
|
+
unit.create.push(contextOp);
|
|
12172
|
+
op.context = contextOp.xref;
|
|
12173
|
+
blockContextByI18nBlock.set(op.xref, contextOp);
|
|
12118
12174
|
}
|
|
12119
12175
|
break;
|
|
12176
|
+
}
|
|
12177
|
+
}
|
|
12178
|
+
}
|
|
12179
|
+
// Assign i18n contexts for child i18n blocks. These don't need their own conext, instead they
|
|
12180
|
+
// should inherit from their root i18n block.
|
|
12181
|
+
for (const unit of job.units) {
|
|
12182
|
+
for (const op of unit.create) {
|
|
12183
|
+
if (op.kind === OpKind.I18nStart && op.xref !== op.root) {
|
|
12184
|
+
const rootContext = blockContextByI18nBlock.get(op.root);
|
|
12185
|
+
if (rootContext === undefined) {
|
|
12186
|
+
throw Error('AssertionError: Root i18n block i18n context should have been created.');
|
|
12187
|
+
}
|
|
12188
|
+
op.context = rootContext.xref;
|
|
12189
|
+
blockContextByI18nBlock.set(op.xref, rootContext);
|
|
12190
|
+
}
|
|
12191
|
+
}
|
|
12192
|
+
}
|
|
12193
|
+
// Create or assign i18n contexts for ICUs.
|
|
12194
|
+
let currentI18nOp = null;
|
|
12195
|
+
for (const unit of job.units) {
|
|
12196
|
+
for (const op of unit.create) {
|
|
12197
|
+
switch (op.kind) {
|
|
12198
|
+
case OpKind.I18nStart:
|
|
12199
|
+
currentI18nOp = op;
|
|
12200
|
+
break;
|
|
12120
12201
|
case OpKind.I18nEnd:
|
|
12121
12202
|
currentI18nOp = null;
|
|
12122
12203
|
break;
|
|
12123
12204
|
case OpKind.IcuStart:
|
|
12124
|
-
// If an ICU represents a different message than its containing block, we give it its own
|
|
12125
|
-
// i18n context.
|
|
12126
12205
|
if (currentI18nOp === null) {
|
|
12127
|
-
throw Error('Unexpected ICU outside of an i18n block.');
|
|
12206
|
+
throw Error('AssertionError: Unexpected ICU outside of an i18n block.');
|
|
12128
12207
|
}
|
|
12129
12208
|
if (op.message.id !== currentI18nOp.message.id) {
|
|
12130
|
-
//
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
|
|
12209
|
+
// This ICU is a sub-message inside its parent i18n block message. We need to give it
|
|
12210
|
+
// its own context.
|
|
12211
|
+
const contextOp = createI18nContextOp(I18nContextKind.Icu, job.allocateXrefId(), currentI18nOp.xref, op.message, null);
|
|
12212
|
+
unit.create.push(contextOp);
|
|
12213
|
+
op.context = contextOp.xref;
|
|
12134
12214
|
}
|
|
12135
12215
|
else {
|
|
12136
|
-
//
|
|
12137
|
-
// the
|
|
12216
|
+
// This ICU is the only translatable content in its parent i18n block. We need to
|
|
12217
|
+
// convert the parent's context into an ICU context.
|
|
12138
12218
|
op.context = currentI18nOp.context;
|
|
12219
|
+
blockContextByI18nBlock.get(currentI18nOp.xref).contextKind = I18nContextKind.Icu;
|
|
12139
12220
|
}
|
|
12140
12221
|
break;
|
|
12141
12222
|
}
|
|
12142
12223
|
}
|
|
12143
|
-
for (const op of unit.ops()) {
|
|
12144
|
-
switch (op.kind) {
|
|
12145
|
-
case OpKind.Binding:
|
|
12146
|
-
case OpKind.Property:
|
|
12147
|
-
case OpKind.Attribute:
|
|
12148
|
-
case OpKind.ExtractedAttribute:
|
|
12149
|
-
if (!op.i18nMessage) {
|
|
12150
|
-
continue;
|
|
12151
|
-
}
|
|
12152
|
-
if (!messageToContext.has(op.i18nMessage)) {
|
|
12153
|
-
// create the context
|
|
12154
|
-
const i18nContext = job.allocateXrefId();
|
|
12155
|
-
unit.create.push(createI18nContextOp(I18nContextKind.Attr, i18nContext, null, op.i18nMessage, null));
|
|
12156
|
-
messageToContext.set(op.i18nMessage, i18nContext);
|
|
12157
|
-
}
|
|
12158
|
-
op.i18nContext = messageToContext.get(op.i18nMessage);
|
|
12159
|
-
break;
|
|
12160
|
-
}
|
|
12161
|
-
}
|
|
12162
12224
|
}
|
|
12163
|
-
|
|
12164
|
-
|
|
12225
|
+
}
|
|
12226
|
+
|
|
12227
|
+
/**
|
|
12228
|
+
* Deduplicate text bindings, e.g. <div class="cls1" class="cls2">
|
|
12229
|
+
*/
|
|
12230
|
+
function deduplicateTextBindings(job) {
|
|
12231
|
+
const seen = new Map();
|
|
12165
12232
|
for (const unit of job.units) {
|
|
12166
|
-
for (const op of unit.
|
|
12167
|
-
if (op.kind === OpKind.
|
|
12168
|
-
|
|
12233
|
+
for (const op of unit.update.reversed()) {
|
|
12234
|
+
if (op.kind === OpKind.Binding && op.isTextAttribute) {
|
|
12235
|
+
const seenForElement = seen.get(op.target) || new Set();
|
|
12236
|
+
if (seenForElement.has(op.name)) {
|
|
12237
|
+
if (job.compatibility === CompatibilityMode.TemplateDefinitionBuilder) {
|
|
12238
|
+
// For most duplicated attributes, TemplateDefinitionBuilder lists all of the values in
|
|
12239
|
+
// the consts array. However, for style and class attributes it only keeps the last one.
|
|
12240
|
+
// We replicate that behavior here since it has actual consequences for apps with
|
|
12241
|
+
// duplicate class or style attrs.
|
|
12242
|
+
if (op.name === 'style' || op.name === 'class') {
|
|
12243
|
+
OpList.remove(op);
|
|
12244
|
+
}
|
|
12245
|
+
}
|
|
12246
|
+
else {
|
|
12247
|
+
// TODO: Determine the correct behavior. It would probably make sense to merge multiple
|
|
12248
|
+
// style and class attributes. Alternatively we could just throw an error, as HTML
|
|
12249
|
+
// doesn't permit duplicate attributes.
|
|
12250
|
+
}
|
|
12251
|
+
}
|
|
12252
|
+
seenForElement.add(op.name);
|
|
12253
|
+
seen.set(op.target, seenForElement);
|
|
12169
12254
|
}
|
|
12170
12255
|
}
|
|
12171
12256
|
}
|
|
@@ -12551,13 +12636,18 @@ const LIST_DELIMITER = '|';
|
|
|
12551
12636
|
* used in the final output.
|
|
12552
12637
|
*/
|
|
12553
12638
|
function extractI18nMessages(job) {
|
|
12554
|
-
//
|
|
12555
|
-
|
|
12639
|
+
// Create an i18n message for each context.
|
|
12640
|
+
// TODO: Merge the context op with the message op since they're 1:1 anyways.
|
|
12641
|
+
const i18nMessagesByContext = new Map();
|
|
12556
12642
|
const i18nBlocks = new Map();
|
|
12643
|
+
const i18nContexts = new Map();
|
|
12557
12644
|
for (const unit of job.units) {
|
|
12558
12645
|
for (const op of unit.create) {
|
|
12559
12646
|
switch (op.kind) {
|
|
12560
12647
|
case OpKind.I18nContext:
|
|
12648
|
+
const i18nMessageOp = createI18nMessage(job, op);
|
|
12649
|
+
unit.create.push(i18nMessageOp);
|
|
12650
|
+
i18nMessagesByContext.set(op.xref, i18nMessageOp);
|
|
12561
12651
|
i18nContexts.set(op.xref, op);
|
|
12562
12652
|
break;
|
|
12563
12653
|
case OpKind.I18nStart:
|
|
@@ -12566,54 +12656,47 @@ function extractI18nMessages(job) {
|
|
|
12566
12656
|
}
|
|
12567
12657
|
}
|
|
12568
12658
|
}
|
|
12569
|
-
//
|
|
12570
|
-
//
|
|
12571
|
-
|
|
12572
|
-
for (const unit of job.units) {
|
|
12573
|
-
for (const op of unit.create) {
|
|
12574
|
-
if (op.kind !== OpKind.I18nContext || op.contextKind !== I18nContextKind.Attr) {
|
|
12575
|
-
continue;
|
|
12576
|
-
}
|
|
12577
|
-
const i18nMessageOp = createI18nMessage(job, op);
|
|
12578
|
-
unit.create.push(i18nMessageOp);
|
|
12579
|
-
}
|
|
12580
|
-
}
|
|
12581
|
-
// Extract messages from root i18n blocks.
|
|
12582
|
-
const i18nBlockMessages = new Map();
|
|
12583
|
-
for (const unit of job.units) {
|
|
12584
|
-
for (const op of unit.create) {
|
|
12585
|
-
if (op.kind === OpKind.I18nStart && op.xref === op.root) {
|
|
12586
|
-
if (!op.context) {
|
|
12587
|
-
throw Error('I18n start op should have its context set.');
|
|
12588
|
-
}
|
|
12589
|
-
const i18nMessageOp = createI18nMessage(job, i18nContexts.get(op.context));
|
|
12590
|
-
i18nBlockMessages.set(op.xref, i18nMessageOp);
|
|
12591
|
-
unit.create.push(i18nMessageOp);
|
|
12592
|
-
}
|
|
12593
|
-
}
|
|
12594
|
-
}
|
|
12595
|
-
// Extract messages from ICUs with their own sub-context.
|
|
12659
|
+
// Associate sub-messages for ICUs with their root message. At this point we can also remove the
|
|
12660
|
+
// ICU start/end ops, as they are no longer needed.
|
|
12661
|
+
let currentIcu = null;
|
|
12596
12662
|
for (const unit of job.units) {
|
|
12597
12663
|
for (const op of unit.create) {
|
|
12598
12664
|
switch (op.kind) {
|
|
12599
12665
|
case OpKind.IcuStart:
|
|
12600
|
-
|
|
12601
|
-
|
|
12666
|
+
currentIcu = op;
|
|
12667
|
+
OpList.remove(op);
|
|
12668
|
+
// Skip any contexts not associated with an ICU.
|
|
12669
|
+
const icuContext = i18nContexts.get(op.context);
|
|
12670
|
+
if (icuContext.contextKind !== I18nContextKind.Icu) {
|
|
12671
|
+
continue;
|
|
12602
12672
|
}
|
|
12603
|
-
|
|
12604
|
-
|
|
12605
|
-
|
|
12606
|
-
|
|
12607
|
-
|
|
12608
|
-
const subMessage = createI18nMessage(job, i18nContext, op.messagePlaceholder);
|
|
12609
|
-
unit.create.push(subMessage);
|
|
12610
|
-
const rootI18nId = i18nBlocks.get(i18nContext.i18nBlock).root;
|
|
12611
|
-
const parentMessage = i18nBlockMessages.get(rootI18nId);
|
|
12612
|
-
parentMessage?.subMessages.push(subMessage.xref);
|
|
12673
|
+
// Skip ICUs that share a context with their i18n message. These represent root-level
|
|
12674
|
+
// ICUs, not sub-messages.
|
|
12675
|
+
const i18nBlock = i18nBlocks.get(icuContext.i18nBlock);
|
|
12676
|
+
if (i18nBlock.context === icuContext.xref) {
|
|
12677
|
+
continue;
|
|
12613
12678
|
}
|
|
12614
|
-
|
|
12679
|
+
// Find the root message and push this ICUs message as a sub-message.
|
|
12680
|
+
const rootI18nBlock = i18nBlocks.get(i18nBlock.root);
|
|
12681
|
+
const rootMessage = i18nMessagesByContext.get(rootI18nBlock.context);
|
|
12682
|
+
if (rootMessage === undefined) {
|
|
12683
|
+
throw Error('AssertionError: ICU sub-message should belong to a root message.');
|
|
12684
|
+
}
|
|
12685
|
+
const subMessage = i18nMessagesByContext.get(icuContext.xref);
|
|
12686
|
+
subMessage.messagePlaceholder = op.messagePlaceholder;
|
|
12687
|
+
rootMessage.subMessages.push(subMessage.xref);
|
|
12615
12688
|
break;
|
|
12616
12689
|
case OpKind.IcuEnd:
|
|
12690
|
+
currentIcu = null;
|
|
12691
|
+
OpList.remove(op);
|
|
12692
|
+
break;
|
|
12693
|
+
case OpKind.IcuPlaceholder:
|
|
12694
|
+
// Add ICU placeholders to the message, then remove the ICU placeholder ops.
|
|
12695
|
+
if (currentIcu === null || currentIcu.context == null) {
|
|
12696
|
+
throw Error('AssertionError: Unexpected ICU placeholder outside of i18n context');
|
|
12697
|
+
}
|
|
12698
|
+
const msg = i18nMessagesByContext.get(currentIcu.context);
|
|
12699
|
+
msg.postprocessingParams.set(op.name, literal(formatIcuPlaceholder(op)));
|
|
12617
12700
|
OpList.remove(op);
|
|
12618
12701
|
break;
|
|
12619
12702
|
}
|
|
@@ -12626,14 +12709,19 @@ function extractI18nMessages(job) {
|
|
|
12626
12709
|
function createI18nMessage(job, context, messagePlaceholder) {
|
|
12627
12710
|
let formattedParams = formatParams(context.params);
|
|
12628
12711
|
const formattedPostprocessingParams = formatParams(context.postprocessingParams);
|
|
12629
|
-
let needsPostprocessing =
|
|
12630
|
-
for (const values of context.params.values()) {
|
|
12631
|
-
if (values.length > 1) {
|
|
12632
|
-
needsPostprocessing = true;
|
|
12633
|
-
}
|
|
12634
|
-
}
|
|
12712
|
+
let needsPostprocessing = [...context.params.values()].some(v => v.length > 1);
|
|
12635
12713
|
return createI18nMessageOp(job.allocateXrefId(), context.xref, context.i18nBlock, context.message, messagePlaceholder ?? null, formattedParams, formattedPostprocessingParams, needsPostprocessing);
|
|
12636
12714
|
}
|
|
12715
|
+
/**
|
|
12716
|
+
* Formats an ICU placeholder into a single string with expression placeholders.
|
|
12717
|
+
*/
|
|
12718
|
+
function formatIcuPlaceholder(op) {
|
|
12719
|
+
if (op.strings.length !== op.expressionPlaceholders.length + 1) {
|
|
12720
|
+
throw Error(`AsserionError: Invalid ICU placeholder with ${op.strings.length} strings and ${op.expressionPlaceholders.length} expressions`);
|
|
12721
|
+
}
|
|
12722
|
+
const values = op.expressionPlaceholders.map(formatValue);
|
|
12723
|
+
return op.strings.flatMap((str, i) => [str, values[i] || '']).join('');
|
|
12724
|
+
}
|
|
12637
12725
|
/**
|
|
12638
12726
|
* Formats a map of `I18nParamValue[]` values into a map of `Expression` values.
|
|
12639
12727
|
*/
|
|
@@ -12972,7 +13060,7 @@ const BANG_IMPORTANT = '!important';
|
|
|
12972
13060
|
*/
|
|
12973
13061
|
function parseHostStyleProperties(job) {
|
|
12974
13062
|
for (const op of job.root.update) {
|
|
12975
|
-
if (op.kind
|
|
13063
|
+
if (!(op.kind === OpKind.Binding && op.bindingKind === BindingKind.Property)) {
|
|
12976
13064
|
continue;
|
|
12977
13065
|
}
|
|
12978
13066
|
if (op.name.endsWith(BANG_IMPORTANT)) {
|
|
@@ -20130,7 +20218,7 @@ function collectMessage(job, fileBasedI18nSuffix, messages, messageOp) {
|
|
|
20130
20218
|
let transformFn = undefined;
|
|
20131
20219
|
// If nescessary, add a post-processing step and resolve any placeholder params that are
|
|
20132
20220
|
// set in post-processing.
|
|
20133
|
-
if (messageOp.needsPostprocessing) {
|
|
20221
|
+
if (messageOp.needsPostprocessing || messageOp.postprocessingParams.size > 0) {
|
|
20134
20222
|
// Sort the post-processing params for consistency with TemaplateDefinitionBuilder output.
|
|
20135
20223
|
const postprocessingParams = Object.fromEntries([...messageOp.postprocessingParams.entries()].sort());
|
|
20136
20224
|
const formattedPostprocessingParams = formatI18nPlaceholderNamesInMap(postprocessingParams, /* useCamelCase */ false);
|
|
@@ -20160,7 +20248,6 @@ function addSubMessageParams(messageOp, subMessagePlaceholders) {
|
|
|
20160
20248
|
else {
|
|
20161
20249
|
messageOp.params.set(placeholder, literal(`${ESCAPE}${I18N_ICU_MAPPING_PREFIX}${placeholder}${ESCAPE}`));
|
|
20162
20250
|
messageOp.postprocessingParams.set(placeholder, literalArr(subMessages));
|
|
20163
|
-
messageOp.needsPostprocessing = true;
|
|
20164
20251
|
}
|
|
20165
20252
|
}
|
|
20166
20253
|
}
|
|
@@ -20246,6 +20333,7 @@ function convertI18nText(job) {
|
|
|
20246
20333
|
let currentIcu = null;
|
|
20247
20334
|
const textNodeI18nBlocks = new Map();
|
|
20248
20335
|
const textNodeIcus = new Map();
|
|
20336
|
+
const icuPlaceholderByText = new Map();
|
|
20249
20337
|
for (const op of unit.create) {
|
|
20250
20338
|
switch (op.kind) {
|
|
20251
20339
|
case OpKind.I18nStart:
|
|
@@ -20270,7 +20358,19 @@ function convertI18nText(job) {
|
|
|
20270
20358
|
if (currentI18n !== null) {
|
|
20271
20359
|
textNodeI18nBlocks.set(op.xref, currentI18n);
|
|
20272
20360
|
textNodeIcus.set(op.xref, currentIcu);
|
|
20273
|
-
|
|
20361
|
+
if (op.icuPlaceholder !== null) {
|
|
20362
|
+
// Create an op to represent the ICU placeholder. Initially set its static text to the
|
|
20363
|
+
// value of the text op, though this may be overwritten later if this text op is a
|
|
20364
|
+
// placeholder for an interpolation.
|
|
20365
|
+
const icuPlaceholderOp = createIcuPlaceholderOp(job.allocateXrefId(), op.icuPlaceholder, [op.initialValue]);
|
|
20366
|
+
OpList.replace(op, icuPlaceholderOp);
|
|
20367
|
+
icuPlaceholderByText.set(op.xref, icuPlaceholderOp);
|
|
20368
|
+
}
|
|
20369
|
+
else {
|
|
20370
|
+
// Otherwise just remove the text op, since its value is already accounted for in the
|
|
20371
|
+
// translated message.
|
|
20372
|
+
OpList.remove(op);
|
|
20373
|
+
}
|
|
20274
20374
|
}
|
|
20275
20375
|
break;
|
|
20276
20376
|
}
|
|
@@ -20285,6 +20385,7 @@ function convertI18nText(job) {
|
|
|
20285
20385
|
}
|
|
20286
20386
|
const i18nOp = textNodeI18nBlocks.get(op.target);
|
|
20287
20387
|
const icuOp = textNodeIcus.get(op.target);
|
|
20388
|
+
const icuPlaceholder = icuPlaceholderByText.get(op.target);
|
|
20288
20389
|
const contextId = icuOp ? icuOp.context : i18nOp.context;
|
|
20289
20390
|
const resolutionTime = icuOp ? I18nParamResolutionTime.Postproccessing :
|
|
20290
20391
|
I18nParamResolutionTime.Creation;
|
|
@@ -20293,9 +20394,14 @@ function convertI18nText(job) {
|
|
|
20293
20394
|
const expr = op.interpolation.expressions[i];
|
|
20294
20395
|
// For now, this i18nExpression depends on the slot context of the enclosing i18n block.
|
|
20295
20396
|
// Later, we will modify this, and advance to a different point.
|
|
20296
|
-
ops.push(createI18nExpressionOp(contextId, i18nOp.xref, i18nOp.xref, i18nOp.handle, expr, op.interpolation.i18nPlaceholders[i], resolutionTime, I18nExpressionFor.I18nText, '', expr.sourceSpan ?? op.sourceSpan));
|
|
20397
|
+
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));
|
|
20297
20398
|
}
|
|
20298
20399
|
OpList.replaceWithMany(op, ops);
|
|
20400
|
+
// If this interpolation is part of an ICU placeholder, add the strings and expressions to
|
|
20401
|
+
// the placeholder.
|
|
20402
|
+
if (icuPlaceholder !== undefined) {
|
|
20403
|
+
icuPlaceholder.strings = op.interpolation.strings;
|
|
20404
|
+
}
|
|
20299
20405
|
break;
|
|
20300
20406
|
}
|
|
20301
20407
|
}
|
|
@@ -20824,10 +20930,28 @@ function keepLast(ops) {
|
|
|
20824
20930
|
* class property.
|
|
20825
20931
|
*/
|
|
20826
20932
|
function parseExtractedStyles(job) {
|
|
20933
|
+
const elements = new Map();
|
|
20934
|
+
for (const unit of job.units) {
|
|
20935
|
+
for (const op of unit.create) {
|
|
20936
|
+
if (isElementOrContainerOp(op)) {
|
|
20937
|
+
elements.set(op.xref, op);
|
|
20938
|
+
}
|
|
20939
|
+
}
|
|
20940
|
+
}
|
|
20827
20941
|
for (const unit of job.units) {
|
|
20828
20942
|
for (const op of unit.create) {
|
|
20829
20943
|
if (op.kind === OpKind.ExtractedAttribute && op.bindingKind === BindingKind.Attribute &&
|
|
20830
20944
|
isStringLiteral(op.expression)) {
|
|
20945
|
+
const target = elements.get(op.target);
|
|
20946
|
+
if (target !== undefined && target.kind === OpKind.Template &&
|
|
20947
|
+
target.templateKind === TemplateKind.Structural) {
|
|
20948
|
+
// TemplateDefinitionBuilder will not apply class and style bindings to structural
|
|
20949
|
+
// directives; instead, it will leave them as attributes.
|
|
20950
|
+
// (It's not clear what that would mean, anyway -- classes and styles on a structural
|
|
20951
|
+
// element should probably be a parse error.)
|
|
20952
|
+
// TODO: We may be able to remove this once Template Pipeline is the default.
|
|
20953
|
+
continue;
|
|
20954
|
+
}
|
|
20831
20955
|
if (op.name === 'style') {
|
|
20832
20956
|
const parsedStyles = parse(op.expression.value);
|
|
20833
20957
|
for (let i = 0; i < parsedStyles.length - 1; i += 2) {
|
|
@@ -21719,19 +21843,19 @@ function reifyCreateOperations(unit, ops) {
|
|
|
21719
21843
|
OpList.replace(op, text(op.handle.slot, op.initialValue, op.sourceSpan));
|
|
21720
21844
|
break;
|
|
21721
21845
|
case OpKind.ElementStart:
|
|
21722
|
-
OpList.replace(op, elementStart(op.handle.slot, op.tag, op.attributes, op.localRefs, op.
|
|
21846
|
+
OpList.replace(op, elementStart(op.handle.slot, op.tag, op.attributes, op.localRefs, op.startSourceSpan));
|
|
21723
21847
|
break;
|
|
21724
21848
|
case OpKind.Element:
|
|
21725
|
-
OpList.replace(op, element(op.handle.slot, op.tag, op.attributes, op.localRefs, op.
|
|
21849
|
+
OpList.replace(op, element(op.handle.slot, op.tag, op.attributes, op.localRefs, op.wholeSourceSpan));
|
|
21726
21850
|
break;
|
|
21727
21851
|
case OpKind.ElementEnd:
|
|
21728
21852
|
OpList.replace(op, elementEnd(op.sourceSpan));
|
|
21729
21853
|
break;
|
|
21730
21854
|
case OpKind.ContainerStart:
|
|
21731
|
-
OpList.replace(op, elementContainerStart(op.handle.slot, op.attributes, op.localRefs, op.
|
|
21855
|
+
OpList.replace(op, elementContainerStart(op.handle.slot, op.attributes, op.localRefs, op.startSourceSpan));
|
|
21732
21856
|
break;
|
|
21733
21857
|
case OpKind.Container:
|
|
21734
|
-
OpList.replace(op, elementContainer(op.handle.slot, op.attributes, op.localRefs, op.
|
|
21858
|
+
OpList.replace(op, elementContainer(op.handle.slot, op.attributes, op.localRefs, op.wholeSourceSpan));
|
|
21735
21859
|
break;
|
|
21736
21860
|
case OpKind.ContainerEnd:
|
|
21737
21861
|
OpList.replace(op, elementContainerEnd());
|
|
@@ -21759,7 +21883,7 @@ function reifyCreateOperations(unit, ops) {
|
|
|
21759
21883
|
throw new Error(`AssertionError: local refs array should have been extracted into a constant`);
|
|
21760
21884
|
}
|
|
21761
21885
|
const childView = unit.job.views.get(op.xref);
|
|
21762
|
-
OpList.replace(op, template(op.handle.slot, variable(childView.fnName), childView.decls, childView.vars, op.tag, op.attributes, op.localRefs, op.
|
|
21886
|
+
OpList.replace(op, template(op.handle.slot, variable(childView.fnName), childView.decls, childView.vars, op.tag, op.attributes, op.localRefs, op.startSourceSpan));
|
|
21763
21887
|
break;
|
|
21764
21888
|
case OpKind.DisableBindings:
|
|
21765
21889
|
OpList.replace(op, disableBindings());
|
|
@@ -21774,7 +21898,7 @@ function reifyCreateOperations(unit, ops) {
|
|
|
21774
21898
|
const listenerFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, op.consumesDollarEvent);
|
|
21775
21899
|
const eventTargetResolver = op.eventTarget ? GLOBAL_TARGET_RESOLVERS$1.get(op.eventTarget) : null;
|
|
21776
21900
|
if (eventTargetResolver === undefined) {
|
|
21777
|
-
throw new Error(`
|
|
21901
|
+
throw new Error(`Unexpected global target '${op.eventTarget}' defined for '${op.name}' event. Supported list of global targets: window,document,body.`);
|
|
21778
21902
|
}
|
|
21779
21903
|
OpList.replace(op, listener(op.name, listenerFn, eventTargetResolver, op.hostListener && op.isAnimationListener, op.sourceSpan));
|
|
21780
21904
|
break;
|
|
@@ -21861,7 +21985,7 @@ function reifyCreateOperations(unit, ops) {
|
|
|
21861
21985
|
emptyDecls = emptyView.decls;
|
|
21862
21986
|
emptyVars = emptyView.vars;
|
|
21863
21987
|
}
|
|
21864
|
-
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.
|
|
21988
|
+
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.wholeSourceSpan));
|
|
21865
21989
|
break;
|
|
21866
21990
|
case OpKind.Statement:
|
|
21867
21991
|
// Pass statement operations directly through.
|
|
@@ -22491,6 +22615,7 @@ function resolveI18nExpressionPlaceholders(job) {
|
|
|
22491
22615
|
// Record all of the i18n context ops, and the sub-template index for each i18n op.
|
|
22492
22616
|
const subTemplateIndicies = new Map();
|
|
22493
22617
|
const i18nContexts = new Map();
|
|
22618
|
+
const icuPlaceholders = new Map();
|
|
22494
22619
|
for (const unit of job.units) {
|
|
22495
22620
|
for (const op of unit.create) {
|
|
22496
22621
|
switch (op.kind) {
|
|
@@ -22500,6 +22625,9 @@ function resolveI18nExpressionPlaceholders(job) {
|
|
|
22500
22625
|
case OpKind.I18nContext:
|
|
22501
22626
|
i18nContexts.set(op.xref, op);
|
|
22502
22627
|
break;
|
|
22628
|
+
case OpKind.IcuPlaceholder:
|
|
22629
|
+
icuPlaceholders.set(op.xref, op);
|
|
22630
|
+
break;
|
|
22503
22631
|
}
|
|
22504
22632
|
}
|
|
22505
22633
|
}
|
|
@@ -22513,76 +22641,32 @@ function resolveI18nExpressionPlaceholders(job) {
|
|
|
22513
22641
|
for (const unit of job.units) {
|
|
22514
22642
|
for (const op of unit.update) {
|
|
22515
22643
|
if (op.kind === OpKind.I18nExpression) {
|
|
22516
|
-
const i18nContext = i18nContexts.get(op.context);
|
|
22517
22644
|
const index = expressionIndices.get(referenceIndex(op)) || 0;
|
|
22518
22645
|
const subTemplateIndex = subTemplateIndicies.get(op.i18nOwner) ?? null;
|
|
22519
|
-
|
|
22520
|
-
const params = op.resolutionTime === I18nParamResolutionTime.Creation ?
|
|
22521
|
-
i18nContext.params :
|
|
22522
|
-
i18nContext.postprocessingParams;
|
|
22523
|
-
const values = params.get(op.i18nPlaceholder) || [];
|
|
22524
|
-
values.push({
|
|
22646
|
+
const value = {
|
|
22525
22647
|
value: index,
|
|
22526
22648
|
subTemplateIndex: subTemplateIndex,
|
|
22527
22649
|
flags: I18nParamValueFlags.ExpressionIndex
|
|
22528
|
-
}
|
|
22529
|
-
|
|
22650
|
+
};
|
|
22651
|
+
updatePlaceholder(op, value, i18nContexts, icuPlaceholders);
|
|
22530
22652
|
expressionIndices.set(referenceIndex(op), index + 1);
|
|
22531
22653
|
}
|
|
22532
22654
|
}
|
|
22533
22655
|
}
|
|
22534
22656
|
}
|
|
22535
|
-
|
|
22536
|
-
|
|
22537
|
-
|
|
22538
|
-
|
|
22539
|
-
|
|
22540
|
-
|
|
22541
|
-
|
|
22542
|
-
|
|
22543
|
-
|
|
22544
|
-
node.visit(new ResolveIcuPlaceholdersVisitor(op.postprocessingParams));
|
|
22545
|
-
}
|
|
22546
|
-
}
|
|
22547
|
-
}
|
|
22548
|
-
}
|
|
22549
|
-
}
|
|
22550
|
-
/**
|
|
22551
|
-
* Visitor for i18n AST that resolves ICU params into the given map.
|
|
22552
|
-
*/
|
|
22553
|
-
class ResolveIcuPlaceholdersVisitor extends RecurseVisitor {
|
|
22554
|
-
constructor(params) {
|
|
22555
|
-
super();
|
|
22556
|
-
this.params = params;
|
|
22557
|
-
}
|
|
22558
|
-
visitContainerPlaceholder(placeholder) {
|
|
22559
|
-
// Add the start and end source span for container placeholders. These need to be recorded for
|
|
22560
|
-
// elements inside ICUs. The slots for the nodes were recorded separately under the i18n
|
|
22561
|
-
// block's context as part of the `resolveI18nElementPlaceholders` phase.
|
|
22562
|
-
if (placeholder.startName && placeholder.startSourceSpan &&
|
|
22563
|
-
!this.params.has(placeholder.startName)) {
|
|
22564
|
-
this.params.set(placeholder.startName, [{
|
|
22565
|
-
value: placeholder.startSourceSpan?.toString(),
|
|
22566
|
-
subTemplateIndex: null,
|
|
22567
|
-
flags: I18nParamValueFlags.None
|
|
22568
|
-
}]);
|
|
22569
|
-
}
|
|
22570
|
-
if (placeholder.closeName && placeholder.endSourceSpan &&
|
|
22571
|
-
!this.params.has(placeholder.closeName)) {
|
|
22572
|
-
this.params.set(placeholder.closeName, [{
|
|
22573
|
-
value: placeholder.endSourceSpan?.toString(),
|
|
22574
|
-
subTemplateIndex: null,
|
|
22575
|
-
flags: I18nParamValueFlags.None
|
|
22576
|
-
}]);
|
|
22577
|
-
}
|
|
22578
|
-
}
|
|
22579
|
-
visitTagPlaceholder(placeholder) {
|
|
22580
|
-
super.visitTagPlaceholder(placeholder);
|
|
22581
|
-
this.visitContainerPlaceholder(placeholder);
|
|
22657
|
+
function updatePlaceholder(op, value, i18nContexts, icuPlaceholders) {
|
|
22658
|
+
if (op.i18nPlaceholder !== null) {
|
|
22659
|
+
const i18nContext = i18nContexts.get(op.context);
|
|
22660
|
+
const params = op.resolutionTime === I18nParamResolutionTime.Creation ?
|
|
22661
|
+
i18nContext.params :
|
|
22662
|
+
i18nContext.postprocessingParams;
|
|
22663
|
+
const values = params.get(op.i18nPlaceholder) || [];
|
|
22664
|
+
values.push(value);
|
|
22665
|
+
params.set(op.i18nPlaceholder, values);
|
|
22582
22666
|
}
|
|
22583
|
-
|
|
22584
|
-
|
|
22585
|
-
|
|
22667
|
+
if (op.icuPlaceholder !== null) {
|
|
22668
|
+
const icuPlaceholderOp = icuPlaceholders.get(op.icuPlaceholder);
|
|
22669
|
+
icuPlaceholderOp?.expressionPlaceholders.push(value);
|
|
22586
22670
|
}
|
|
22587
22671
|
}
|
|
22588
22672
|
|
|
@@ -23257,7 +23341,14 @@ function varsUsedByOp(op) {
|
|
|
23257
23341
|
return op.interpolation.expressions.length;
|
|
23258
23342
|
case OpKind.I18nExpression:
|
|
23259
23343
|
case OpKind.Conditional:
|
|
23344
|
+
case OpKind.DeferWhen:
|
|
23260
23345
|
return 1;
|
|
23346
|
+
case OpKind.RepeaterCreate:
|
|
23347
|
+
// Repeaters may require an extra variable binding slot, if they have an empty view, for the
|
|
23348
|
+
// empty block tracking.
|
|
23349
|
+
// TODO: It's a bit odd to have a create mode instruction consume variable slots. Maybe we can
|
|
23350
|
+
// find a way to use the Repeater update op instead.
|
|
23351
|
+
return op.emptyView ? 1 : 0;
|
|
23261
23352
|
default:
|
|
23262
23353
|
throw new Error(`Unhandled op: ${OpKind[op.kind]}`);
|
|
23263
23354
|
}
|
|
@@ -23741,6 +23832,7 @@ const phases = [
|
|
|
23741
23832
|
{ kind: CompilationJobKind.Tmpl, fn: emitNamespaceChanges },
|
|
23742
23833
|
{ kind: CompilationJobKind.Tmpl, fn: propagateI18nBlocks },
|
|
23743
23834
|
{ kind: CompilationJobKind.Tmpl, fn: wrapI18nIcus },
|
|
23835
|
+
{ kind: CompilationJobKind.Both, fn: deduplicateTextBindings },
|
|
23744
23836
|
{ kind: CompilationJobKind.Both, fn: specializeStyleBindings },
|
|
23745
23837
|
{ kind: CompilationJobKind.Both, fn: specializeBindings },
|
|
23746
23838
|
{ kind: CompilationJobKind.Both, fn: extractAttributes },
|
|
@@ -23779,7 +23871,6 @@ const phases = [
|
|
|
23779
23871
|
{ kind: CompilationJobKind.Tmpl, fn: createDeferDepsFns },
|
|
23780
23872
|
{ kind: CompilationJobKind.Tmpl, fn: resolveI18nElementPlaceholders },
|
|
23781
23873
|
{ kind: CompilationJobKind.Tmpl, fn: resolveI18nExpressionPlaceholders },
|
|
23782
|
-
{ kind: CompilationJobKind.Tmpl, fn: resolveI18nIcuPlaceholders },
|
|
23783
23874
|
{ kind: CompilationJobKind.Tmpl, fn: extractI18nMessages },
|
|
23784
23875
|
{ kind: CompilationJobKind.Tmpl, fn: generateTrackFns },
|
|
23785
23876
|
{ kind: CompilationJobKind.Tmpl, fn: collectI18nConsts },
|
|
@@ -23939,7 +24030,7 @@ function ingestHostBinding(input, bindingParser, constantPool) {
|
|
|
23939
24030
|
const securityContexts = bindingParser
|
|
23940
24031
|
.calcPossibleSecurityContexts(input.componentSelector, property.name, bindingKind === BindingKind.Attribute)
|
|
23941
24032
|
.filter(context => context !== SecurityContext.NONE);
|
|
23942
|
-
ingestHostProperty(job, property, bindingKind,
|
|
24033
|
+
ingestHostProperty(job, property, bindingKind, securityContexts);
|
|
23943
24034
|
}
|
|
23944
24035
|
for (const [name, expr] of Object.entries(input.attributes) ?? []) {
|
|
23945
24036
|
const securityContexts = bindingParser.calcPossibleSecurityContexts(input.componentSelector, name, true)
|
|
@@ -23953,7 +24044,7 @@ function ingestHostBinding(input, bindingParser, constantPool) {
|
|
|
23953
24044
|
}
|
|
23954
24045
|
// TODO: We should refactor the parser to use the same types and structures for host bindings as
|
|
23955
24046
|
// with ordinary components. This would allow us to share a lot more ingestion code.
|
|
23956
|
-
function ingestHostProperty(job, property, bindingKind,
|
|
24047
|
+
function ingestHostProperty(job, property, bindingKind, securityContexts) {
|
|
23957
24048
|
let expression;
|
|
23958
24049
|
const ast = property.expression.ast;
|
|
23959
24050
|
if (ast instanceof Interpolation$1) {
|
|
@@ -23962,20 +24053,21 @@ function ingestHostProperty(job, property, bindingKind, isTextAttribute, securit
|
|
|
23962
24053
|
else {
|
|
23963
24054
|
expression = convertAst(ast, job, property.sourceSpan);
|
|
23964
24055
|
}
|
|
23965
|
-
job.root.update.push(createBindingOp(job.root.xref, bindingKind, property.name, expression, null, securityContexts,
|
|
24056
|
+
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));
|
|
23966
24057
|
}
|
|
23967
24058
|
function ingestHostAttribute(job, name, value, securityContexts) {
|
|
23968
|
-
const attrBinding = createBindingOp(job.root.xref, BindingKind.Attribute, name, value, null, securityContexts,
|
|
24059
|
+
const attrBinding = createBindingOp(job.root.xref, BindingKind.Attribute, name, value, null, securityContexts,
|
|
24060
|
+
/* Host attributes should always be extracted to const hostAttrs, even if they are not
|
|
24061
|
+
*strictly* text literals */
|
|
24062
|
+
true, false, null,
|
|
23969
24063
|
/* TODO */ null,
|
|
23970
|
-
|
|
24064
|
+
/** TODO: May be null? */ value.sourceSpan);
|
|
23971
24065
|
job.root.update.push(attrBinding);
|
|
23972
24066
|
}
|
|
23973
24067
|
function ingestHostEvent(job, event) {
|
|
23974
24068
|
const [phase, target] = event.type === 0 /* e.ParsedEventType.Regular */ ? [null, event.targetOrPhase] :
|
|
23975
24069
|
[event.targetOrPhase, null];
|
|
23976
|
-
const eventBinding = createListenerOp(job.root.xref, new SlotHandle(), event.name, null,
|
|
23977
|
-
// TODO: Can this be a chain?
|
|
23978
|
-
eventBinding.handlerOps.push(createStatementOp(new ReturnStatement(convertAst(event.handler.ast, job, event.sourceSpan), event.handlerSpan)));
|
|
24070
|
+
const eventBinding = createListenerOp(job.root.xref, new SlotHandle(), event.name, null, makeListenerHandlerOps(job.root, event.handler, event.handlerSpan), phase, target, true, event.sourceSpan);
|
|
23979
24071
|
job.root.create.push(eventBinding);
|
|
23980
24072
|
}
|
|
23981
24073
|
/**
|
|
@@ -23993,10 +24085,10 @@ function ingestNodes(unit, template) {
|
|
|
23993
24085
|
ingestContent(unit, node);
|
|
23994
24086
|
}
|
|
23995
24087
|
else if (node instanceof Text$3) {
|
|
23996
|
-
ingestText(unit, node);
|
|
24088
|
+
ingestText(unit, node, null);
|
|
23997
24089
|
}
|
|
23998
24090
|
else if (node instanceof BoundText) {
|
|
23999
|
-
ingestBoundText(unit, node);
|
|
24091
|
+
ingestBoundText(unit, node, null);
|
|
24000
24092
|
}
|
|
24001
24093
|
else if (node instanceof IfBlock) {
|
|
24002
24094
|
ingestIfBlock(unit, node);
|
|
@@ -24028,7 +24120,7 @@ function ingestElement(unit, element) {
|
|
|
24028
24120
|
}
|
|
24029
24121
|
const id = unit.job.allocateXrefId();
|
|
24030
24122
|
const [namespaceKey, elementName] = splitNsName(element.name);
|
|
24031
|
-
const startOp = createElementStartOp(elementName, id, namespaceForKey(namespaceKey), element.i18n instanceof TagPlaceholder ? element.i18n : undefined, element.startSourceSpan);
|
|
24123
|
+
const startOp = createElementStartOp(elementName, id, namespaceForKey(namespaceKey), element.i18n instanceof TagPlaceholder ? element.i18n : undefined, element.startSourceSpan, element.sourceSpan);
|
|
24032
24124
|
unit.create.push(startOp);
|
|
24033
24125
|
ingestElementBindings(unit, startOp, element);
|
|
24034
24126
|
ingestReferences(startOp, element);
|
|
@@ -24071,7 +24163,7 @@ function ingestTemplate(unit, tmpl) {
|
|
|
24071
24163
|
'' :
|
|
24072
24164
|
prefixWithNamespace(tagNameWithoutNamespace, namespace);
|
|
24073
24165
|
const templateKind = isPlainTemplate(tmpl) ? TemplateKind.NgTemplate : TemplateKind.Structural;
|
|
24074
|
-
const templateOp = createTemplateOp(childView.xref, templateKind, tagNameWithoutNamespace, functionNameSuffix, namespace, i18nPlaceholder, tmpl.startSourceSpan);
|
|
24166
|
+
const templateOp = createTemplateOp(childView.xref, templateKind, tagNameWithoutNamespace, functionNameSuffix, namespace, i18nPlaceholder, tmpl.startSourceSpan, tmpl.sourceSpan);
|
|
24075
24167
|
unit.create.push(templateOp);
|
|
24076
24168
|
ingestTemplateBindings(unit, templateOp, tmpl, templateKind);
|
|
24077
24169
|
ingestReferences(templateOp, tmpl);
|
|
@@ -24106,13 +24198,13 @@ function ingestContent(unit, content) {
|
|
|
24106
24198
|
/**
|
|
24107
24199
|
* Ingest a literal text node from the AST into the given `ViewCompilation`.
|
|
24108
24200
|
*/
|
|
24109
|
-
function ingestText(unit, text) {
|
|
24110
|
-
unit.create.push(createTextOp(unit.job.allocateXrefId(), text.value, text.sourceSpan));
|
|
24201
|
+
function ingestText(unit, text, icuPlaceholder) {
|
|
24202
|
+
unit.create.push(createTextOp(unit.job.allocateXrefId(), text.value, icuPlaceholder, text.sourceSpan));
|
|
24111
24203
|
}
|
|
24112
24204
|
/**
|
|
24113
24205
|
* Ingest an interpolated text node from the AST into the given `ViewCompilation`.
|
|
24114
24206
|
*/
|
|
24115
|
-
function ingestBoundText(unit, text,
|
|
24207
|
+
function ingestBoundText(unit, text, icuPlaceholder) {
|
|
24116
24208
|
let value = text.value;
|
|
24117
24209
|
if (value instanceof ASTWithSource) {
|
|
24118
24210
|
value = value.ast;
|
|
@@ -24123,19 +24215,16 @@ function ingestBoundText(unit, text, i18nPlaceholders) {
|
|
|
24123
24215
|
if (text.i18n !== undefined && !(text.i18n instanceof Container)) {
|
|
24124
24216
|
throw Error(`Unhandled i18n metadata type for text interpolation: ${text.i18n?.constructor.name}`);
|
|
24125
24217
|
}
|
|
24126
|
-
|
|
24127
|
-
|
|
24128
|
-
|
|
24129
|
-
|
|
24130
|
-
|
|
24131
|
-
.map(placeholder => placeholder.name) :
|
|
24132
|
-
[];
|
|
24133
|
-
}
|
|
24218
|
+
const i18nPlaceholders = text.i18n instanceof Container ?
|
|
24219
|
+
text.i18n.children
|
|
24220
|
+
.filter((node) => node instanceof Placeholder)
|
|
24221
|
+
.map(placeholder => placeholder.name) :
|
|
24222
|
+
[];
|
|
24134
24223
|
if (i18nPlaceholders.length > 0 && i18nPlaceholders.length !== value.expressions.length) {
|
|
24135
24224
|
throw Error(`Unexpected number of i18n placeholders (${value.expressions.length}) for BoundText with ${value.expressions.length} expressions`);
|
|
24136
24225
|
}
|
|
24137
24226
|
const textXref = unit.job.allocateXrefId();
|
|
24138
|
-
unit.create.push(createTextOp(textXref, '', text.sourceSpan));
|
|
24227
|
+
unit.create.push(createTextOp(textXref, '', icuPlaceholder, text.sourceSpan));
|
|
24139
24228
|
// TemplateDefinitionBuilder does not generate source maps for sub-expressions inside an
|
|
24140
24229
|
// interpolation. We copy that behavior in compatibility mode.
|
|
24141
24230
|
// TODO: is it actually correct to generate these extra maps in modern mode?
|
|
@@ -24168,7 +24257,7 @@ function ingestIfBlock(unit, ifBlock) {
|
|
|
24168
24257
|
}
|
|
24169
24258
|
ifCaseI18nMeta = ifCase.i18n;
|
|
24170
24259
|
}
|
|
24171
|
-
const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, tagName, 'Conditional', Namespace.HTML, ifCaseI18nMeta, ifCase.sourceSpan);
|
|
24260
|
+
const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, tagName, 'Conditional', Namespace.HTML, ifCaseI18nMeta, ifCase.startSourceSpan, ifCase.sourceSpan);
|
|
24172
24261
|
unit.create.push(templateOp);
|
|
24173
24262
|
if (firstXref === null) {
|
|
24174
24263
|
firstXref = cView.xref;
|
|
@@ -24198,7 +24287,7 @@ function ingestSwitchBlock(unit, switchBlock) {
|
|
|
24198
24287
|
}
|
|
24199
24288
|
switchCaseI18nMeta = switchCase.i18n;
|
|
24200
24289
|
}
|
|
24201
|
-
const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, null, 'Case', Namespace.HTML, switchCaseI18nMeta, switchCase.sourceSpan);
|
|
24290
|
+
const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, null, 'Case', Namespace.HTML, switchCaseI18nMeta, switchCase.startSourceSpan, switchCase.sourceSpan);
|
|
24202
24291
|
unit.create.push(templateOp);
|
|
24203
24292
|
if (firstXref === null) {
|
|
24204
24293
|
firstXref = cView.xref;
|
|
@@ -24223,7 +24312,7 @@ function ingestDeferView(unit, suffix, i18nMeta, children, sourceSpan) {
|
|
|
24223
24312
|
}
|
|
24224
24313
|
const secondaryView = unit.job.allocateView(unit.xref);
|
|
24225
24314
|
ingestNodes(secondaryView, children);
|
|
24226
|
-
const templateOp = createTemplateOp(secondaryView.xref, TemplateKind.Block, null, `Defer${suffix}`, Namespace.HTML, i18nMeta, sourceSpan);
|
|
24315
|
+
const templateOp = createTemplateOp(secondaryView.xref, TemplateKind.Block, null, `Defer${suffix}`, Namespace.HTML, i18nMeta, sourceSpan, sourceSpan);
|
|
24227
24316
|
unit.create.push(templateOp);
|
|
24228
24317
|
return templateOp;
|
|
24229
24318
|
}
|
|
@@ -24301,6 +24390,11 @@ function ingestDeferBlock(unit, deferBlock) {
|
|
|
24301
24390
|
deferOnOps.push(deferOnOp);
|
|
24302
24391
|
}
|
|
24303
24392
|
if (triggers.when !== undefined) {
|
|
24393
|
+
if (triggers.when.value instanceof Interpolation$1) {
|
|
24394
|
+
// TemplateDefinitionBuilder supports this case, but it's very strange to me. What would it
|
|
24395
|
+
// even mean?
|
|
24396
|
+
throw new Error(`Unexpected interpolation in defer block when trigger`);
|
|
24397
|
+
}
|
|
24304
24398
|
const deferOnOp = createDeferWhenOp(deferXref, convertAst(triggers.when.value, unit.job, triggers.when.sourceSpan), prefetch, triggers.when.sourceSpan);
|
|
24305
24399
|
deferWhenOps.push(deferOnOp);
|
|
24306
24400
|
}
|
|
@@ -24320,10 +24414,10 @@ function ingestIcu(unit, icu) {
|
|
|
24320
24414
|
unit.create.push(createIcuStartOp(xref, icu.i18n, icuFromI18nMessage(icu.i18n).name, null));
|
|
24321
24415
|
for (const [placeholder, text] of Object.entries({ ...icu.vars, ...icu.placeholders })) {
|
|
24322
24416
|
if (text instanceof BoundText) {
|
|
24323
|
-
ingestBoundText(unit, text,
|
|
24417
|
+
ingestBoundText(unit, text, placeholder);
|
|
24324
24418
|
}
|
|
24325
24419
|
else {
|
|
24326
|
-
ingestText(unit, text);
|
|
24420
|
+
ingestText(unit, text, placeholder);
|
|
24327
24421
|
}
|
|
24328
24422
|
}
|
|
24329
24423
|
unit.create.push(createIcuEndOp(xref));
|
|
@@ -24380,7 +24474,7 @@ function ingestForBlock(unit, forBlock) {
|
|
|
24380
24474
|
const i18nPlaceholder = forBlock.i18n;
|
|
24381
24475
|
const emptyI18nPlaceholder = forBlock.empty?.i18n;
|
|
24382
24476
|
const tagName = ingestControlFlowInsertionPoint(unit, repeaterView.xref, forBlock);
|
|
24383
|
-
const repeaterCreate = createRepeaterCreateOp(repeaterView.xref, emptyView?.xref ?? null, tagName, track, varNames, i18nPlaceholder, emptyI18nPlaceholder, forBlock.sourceSpan);
|
|
24477
|
+
const repeaterCreate = createRepeaterCreateOp(repeaterView.xref, emptyView?.xref ?? null, tagName, track, varNames, i18nPlaceholder, emptyI18nPlaceholder, forBlock.startSourceSpan, forBlock.sourceSpan);
|
|
24384
24478
|
unit.create.push(repeaterCreate);
|
|
24385
24479
|
const expression = convertAst(forBlock.expression, unit.job, convertSourceSpan(forBlock.expression.span, forBlock.sourceSpan));
|
|
24386
24480
|
const repeater = createRepeaterOp(repeaterCreate.xref, repeaterCreate.handle, expression, forBlock.sourceSpan);
|
|
@@ -24498,13 +24592,13 @@ function convertAst(ast, job, baseSourceSpan) {
|
|
|
24498
24592
|
throw new Error(`Unhandled expression type "${ast.constructor.name}" in file "${baseSourceSpan?.start.file.url}"`);
|
|
24499
24593
|
}
|
|
24500
24594
|
}
|
|
24501
|
-
function convertAstWithInterpolation(job, value, i18nMeta) {
|
|
24595
|
+
function convertAstWithInterpolation(job, value, i18nMeta, sourceSpan) {
|
|
24502
24596
|
let expression;
|
|
24503
24597
|
if (value instanceof Interpolation$1) {
|
|
24504
|
-
expression = new Interpolation(value.strings, value.expressions.map(e => convertAst(e, job, null)), Object.keys(asMessage(i18nMeta)?.placeholders ?? {}));
|
|
24598
|
+
expression = new Interpolation(value.strings, value.expressions.map(e => convertAst(e, job, sourceSpan ?? null)), Object.keys(asMessage(i18nMeta)?.placeholders ?? {}));
|
|
24505
24599
|
}
|
|
24506
24600
|
else if (value instanceof AST) {
|
|
24507
|
-
expression = convertAst(value, job, null);
|
|
24601
|
+
expression = convertAst(value, job, sourceSpan ?? null);
|
|
24508
24602
|
}
|
|
24509
24603
|
else {
|
|
24510
24604
|
expression = literal(value);
|
|
@@ -29479,12 +29573,16 @@ class BindingScope {
|
|
|
29479
29573
|
}
|
|
29480
29574
|
/** Binding scope of a `track` function inside a `for` loop block. */
|
|
29481
29575
|
class TrackByBindingScope extends BindingScope {
|
|
29482
|
-
constructor(parentScope,
|
|
29576
|
+
constructor(parentScope, globalOverrides) {
|
|
29483
29577
|
super(parentScope.bindingLevel + 1, parentScope);
|
|
29484
|
-
this.
|
|
29578
|
+
this.globalOverrides = globalOverrides;
|
|
29485
29579
|
this.componentAccessCount = 0;
|
|
29486
29580
|
}
|
|
29487
29581
|
get(name) {
|
|
29582
|
+
// Intercept any overridden globals.
|
|
29583
|
+
if (this.globalOverrides.hasOwnProperty(name)) {
|
|
29584
|
+
return variable(this.globalOverrides[name]);
|
|
29585
|
+
}
|
|
29488
29586
|
let current = this.parent;
|
|
29489
29587
|
// Prevent accesses of template variables outside the `for` loop.
|
|
29490
29588
|
while (current) {
|
|
@@ -29493,10 +29591,6 @@ class TrackByBindingScope extends BindingScope {
|
|
|
29493
29591
|
}
|
|
29494
29592
|
current = current.parent;
|
|
29495
29593
|
}
|
|
29496
|
-
// Intercept any aliased globals.
|
|
29497
|
-
if (this.globalAliases[name]) {
|
|
29498
|
-
return variable(this.globalAliases[name]);
|
|
29499
|
-
}
|
|
29500
29594
|
// When the component scope is accessed, we redirect it through `this`.
|
|
29501
29595
|
this.componentAccessCount++;
|
|
29502
29596
|
return variable('this').prop(name);
|
|
@@ -31994,7 +32088,7 @@ function publishFacade(global) {
|
|
|
31994
32088
|
* @description
|
|
31995
32089
|
* Entry point for all public APIs of the compiler package.
|
|
31996
32090
|
*/
|
|
31997
|
-
const VERSION = new Version('17.0.
|
|
32091
|
+
const VERSION = new Version('17.0.8');
|
|
31998
32092
|
|
|
31999
32093
|
class CompilerConfig {
|
|
32000
32094
|
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
@@ -33560,7 +33654,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
|
|
|
33560
33654
|
function compileDeclareClassMetadata(metadata) {
|
|
33561
33655
|
const definitionMap = new DefinitionMap();
|
|
33562
33656
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
33563
|
-
definitionMap.set('version', literal('17.0.
|
|
33657
|
+
definitionMap.set('version', literal('17.0.8'));
|
|
33564
33658
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33565
33659
|
definitionMap.set('type', metadata.type);
|
|
33566
33660
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -33668,7 +33762,7 @@ function createDirectiveDefinitionMap(meta) {
|
|
|
33668
33762
|
// in 16.1 is actually used.
|
|
33669
33763
|
const minVersion = hasTransformFunctions ? MINIMUM_PARTIAL_LINKER_VERSION$5 : '14.0.0';
|
|
33670
33764
|
definitionMap.set('minVersion', literal(minVersion));
|
|
33671
|
-
definitionMap.set('version', literal('17.0.
|
|
33765
|
+
definitionMap.set('version', literal('17.0.8'));
|
|
33672
33766
|
// e.g. `type: MyDirective`
|
|
33673
33767
|
definitionMap.set('type', meta.type.value);
|
|
33674
33768
|
if (meta.isStandalone) {
|
|
@@ -33945,7 +34039,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
33945
34039
|
function compileDeclareFactoryFunction(meta) {
|
|
33946
34040
|
const definitionMap = new DefinitionMap();
|
|
33947
34041
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
33948
|
-
definitionMap.set('version', literal('17.0.
|
|
34042
|
+
definitionMap.set('version', literal('17.0.8'));
|
|
33949
34043
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33950
34044
|
definitionMap.set('type', meta.type.value);
|
|
33951
34045
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -33980,7 +34074,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
33980
34074
|
function createInjectableDefinitionMap(meta) {
|
|
33981
34075
|
const definitionMap = new DefinitionMap();
|
|
33982
34076
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
33983
|
-
definitionMap.set('version', literal('17.0.
|
|
34077
|
+
definitionMap.set('version', literal('17.0.8'));
|
|
33984
34078
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33985
34079
|
definitionMap.set('type', meta.type.value);
|
|
33986
34080
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -34031,7 +34125,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
34031
34125
|
function createInjectorDefinitionMap(meta) {
|
|
34032
34126
|
const definitionMap = new DefinitionMap();
|
|
34033
34127
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
34034
|
-
definitionMap.set('version', literal('17.0.
|
|
34128
|
+
definitionMap.set('version', literal('17.0.8'));
|
|
34035
34129
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
34036
34130
|
definitionMap.set('type', meta.type.value);
|
|
34037
34131
|
definitionMap.set('providers', meta.providers);
|
|
@@ -34064,7 +34158,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
34064
34158
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
34065
34159
|
}
|
|
34066
34160
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
34067
|
-
definitionMap.set('version', literal('17.0.
|
|
34161
|
+
definitionMap.set('version', literal('17.0.8'));
|
|
34068
34162
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
34069
34163
|
definitionMap.set('type', meta.type.value);
|
|
34070
34164
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -34115,7 +34209,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
34115
34209
|
function createPipeDefinitionMap(meta) {
|
|
34116
34210
|
const definitionMap = new DefinitionMap();
|
|
34117
34211
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
34118
|
-
definitionMap.set('version', literal('17.0.
|
|
34212
|
+
definitionMap.set('version', literal('17.0.8'));
|
|
34119
34213
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
34120
34214
|
// e.g. `type: MyPipe`
|
|
34121
34215
|
definitionMap.set('type', meta.type.value);
|