@angular/compiler 17.0.5 → 17.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/src/compiler.mjs +2 -1
- 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/api.mjs +1 -1
- package/esm2022/src/render3/view/compiler.mjs +20 -8
- package/esm2022/src/render3/view/t2_api.mjs +1 -1
- package/esm2022/src/render3/view/t2_binder.mjs +6 -7
- package/esm2022/src/render3/view/template.mjs +1 -20
- package/esm2022/src/render3/view/util.mjs +24 -2
- package/esm2022/src/template/pipeline/ir/src/enums.mjs +26 -1
- package/esm2022/src/template/pipeline/ir/src/expression.mjs +8 -1
- package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +25 -7
- package/esm2022/src/template/pipeline/ir/src/ops/host.mjs +3 -2
- package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +23 -14
- package/esm2022/src/template/pipeline/src/emit.mjs +10 -6
- package/esm2022/src/template/pipeline/src/ingest.mjs +86 -36
- package/esm2022/src/template/pipeline/src/instruction.mjs +5 -1
- package/esm2022/src/template/pipeline/src/phases/apply_i18n_expressions.mjs +20 -4
- package/esm2022/src/template/pipeline/src/phases/assign_i18n_slot_dependencies.mjs +43 -5
- package/esm2022/src/template/pipeline/src/phases/attribute_extraction.mjs +19 -5
- package/esm2022/src/template/pipeline/src/phases/binding_specialization.mjs +4 -4
- package/esm2022/src/template/pipeline/src/phases/const_collection.mjs +3 -3
- package/esm2022/src/template/pipeline/src/phases/convert_i18n_bindings.mjs +52 -0
- package/esm2022/src/template/pipeline/src/phases/extract_i18n_messages.mjs +65 -88
- package/esm2022/src/template/pipeline/src/phases/generate_advance.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/i18n_const_collection.mjs +143 -35
- package/esm2022/src/template/pipeline/src/phases/i18n_text_extraction.mjs +5 -3
- package/esm2022/src/template/pipeline/src/phases/parse_extracted_styles.mjs +3 -3
- package/esm2022/src/template/pipeline/src/phases/phase_remove_content_selectors.mjs +15 -3
- package/esm2022/src/template/pipeline/src/phases/propagate_i18n_blocks.mjs +5 -1
- package/esm2022/src/template/pipeline/src/phases/reify.mjs +7 -1
- package/esm2022/src/template/pipeline/src/phases/remove_unused_i18n_attrs.mjs +33 -0
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_element_placeholders.mjs +129 -31
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_expression_placeholders.mjs +10 -5
- package/esm2022/src/version.mjs +1 -1
- package/fesm2022/compiler.mjs +793 -315
- package/fesm2022/compiler.mjs.map +1 -1
- package/index.d.ts +21 -1
- package/package.json +2 -2
package/fesm2022/compiler.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v17.0.
|
|
2
|
+
* @license Angular v17.0.6
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -3679,6 +3679,41 @@ function getInjectFn(target) {
|
|
|
3679
3679
|
}
|
|
3680
3680
|
}
|
|
3681
3681
|
|
|
3682
|
+
var TagContentType;
|
|
3683
|
+
(function (TagContentType) {
|
|
3684
|
+
TagContentType[TagContentType["RAW_TEXT"] = 0] = "RAW_TEXT";
|
|
3685
|
+
TagContentType[TagContentType["ESCAPABLE_RAW_TEXT"] = 1] = "ESCAPABLE_RAW_TEXT";
|
|
3686
|
+
TagContentType[TagContentType["PARSABLE_DATA"] = 2] = "PARSABLE_DATA";
|
|
3687
|
+
})(TagContentType || (TagContentType = {}));
|
|
3688
|
+
function splitNsName(elementName) {
|
|
3689
|
+
if (elementName[0] != ':') {
|
|
3690
|
+
return [null, elementName];
|
|
3691
|
+
}
|
|
3692
|
+
const colonIndex = elementName.indexOf(':', 1);
|
|
3693
|
+
if (colonIndex === -1) {
|
|
3694
|
+
throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
|
|
3695
|
+
}
|
|
3696
|
+
return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
|
|
3697
|
+
}
|
|
3698
|
+
// `<ng-container>` tags work the same regardless the namespace
|
|
3699
|
+
function isNgContainer(tagName) {
|
|
3700
|
+
return splitNsName(tagName)[1] === 'ng-container';
|
|
3701
|
+
}
|
|
3702
|
+
// `<ng-content>` tags work the same regardless the namespace
|
|
3703
|
+
function isNgContent(tagName) {
|
|
3704
|
+
return splitNsName(tagName)[1] === 'ng-content';
|
|
3705
|
+
}
|
|
3706
|
+
// `<ng-template>` tags work the same regardless the namespace
|
|
3707
|
+
function isNgTemplate(tagName) {
|
|
3708
|
+
return splitNsName(tagName)[1] === 'ng-template';
|
|
3709
|
+
}
|
|
3710
|
+
function getNsPrefix(fullName) {
|
|
3711
|
+
return fullName === null ? null : splitNsName(fullName)[0];
|
|
3712
|
+
}
|
|
3713
|
+
function mergeNsAndName(prefix, localName) {
|
|
3714
|
+
return prefix ? `:${prefix}:${localName}` : localName;
|
|
3715
|
+
}
|
|
3716
|
+
|
|
3682
3717
|
/**
|
|
3683
3718
|
* This is an R3 `Node`-like wrapper for a raw `html.Comment` node. We do not currently
|
|
3684
3719
|
* require the implementation of a visitor for Comments as they are only collected at
|
|
@@ -4677,7 +4712,7 @@ const I18N_ATTR_PREFIX = 'i18n-';
|
|
|
4677
4712
|
/** Prefix of var expressions used in ICUs */
|
|
4678
4713
|
const I18N_ICU_VAR_PREFIX = 'VAR_';
|
|
4679
4714
|
/** Prefix of ICU expressions for post processing */
|
|
4680
|
-
const I18N_ICU_MAPPING_PREFIX = 'I18N_EXP_';
|
|
4715
|
+
const I18N_ICU_MAPPING_PREFIX$1 = 'I18N_EXP_';
|
|
4681
4716
|
/** Placeholder wrapper for i18n expressions **/
|
|
4682
4717
|
const I18N_PLACEHOLDER_SYMBOL = '�';
|
|
4683
4718
|
function isI18nAttribute(name) {
|
|
@@ -5019,6 +5054,26 @@ class DefinitionMap {
|
|
|
5019
5054
|
return literalMap(this.values);
|
|
5020
5055
|
}
|
|
5021
5056
|
}
|
|
5057
|
+
/**
|
|
5058
|
+
* Creates a `CssSelector` from an AST node.
|
|
5059
|
+
*/
|
|
5060
|
+
function createCssSelectorFromNode(node) {
|
|
5061
|
+
const elementName = node instanceof Element$1 ? node.name : 'ng-template';
|
|
5062
|
+
const attributes = getAttrsForDirectiveMatching(node);
|
|
5063
|
+
const cssSelector = new CssSelector();
|
|
5064
|
+
const elementNameNoNs = splitNsName(elementName)[1];
|
|
5065
|
+
cssSelector.setElement(elementNameNoNs);
|
|
5066
|
+
Object.getOwnPropertyNames(attributes).forEach((name) => {
|
|
5067
|
+
const nameNoNs = splitNsName(name)[1];
|
|
5068
|
+
const value = attributes[name];
|
|
5069
|
+
cssSelector.addAttribute(nameNoNs, value);
|
|
5070
|
+
if (name.toLowerCase() === 'class') {
|
|
5071
|
+
const classes = value.trim().split(/\s+/);
|
|
5072
|
+
classes.forEach(className => cssSelector.addClassName(className));
|
|
5073
|
+
}
|
|
5074
|
+
});
|
|
5075
|
+
return cssSelector;
|
|
5076
|
+
}
|
|
5022
5077
|
/**
|
|
5023
5078
|
* Extract a map of properties to values for a given element or template node, which can be used
|
|
5024
5079
|
* by the directive matching machinery.
|
|
@@ -8915,6 +8970,10 @@ var OpKind;
|
|
|
8915
8970
|
* An i18n context containing information needed to generate an i18n message.
|
|
8916
8971
|
*/
|
|
8917
8972
|
OpKind[OpKind["I18nContext"] = 43] = "I18nContext";
|
|
8973
|
+
/**
|
|
8974
|
+
* A creation op that corresponds to i18n attributes on an element.
|
|
8975
|
+
*/
|
|
8976
|
+
OpKind[OpKind["I18nAttributes"] = 44] = "I18nAttributes";
|
|
8918
8977
|
})(OpKind || (OpKind = {}));
|
|
8919
8978
|
/**
|
|
8920
8979
|
* Distinguishes different kinds of IR expressions.
|
|
@@ -9136,6 +9195,20 @@ var I18nParamResolutionTime;
|
|
|
9136
9195
|
*/
|
|
9137
9196
|
I18nParamResolutionTime[I18nParamResolutionTime["Postproccessing"] = 1] = "Postproccessing";
|
|
9138
9197
|
})(I18nParamResolutionTime || (I18nParamResolutionTime = {}));
|
|
9198
|
+
/**
|
|
9199
|
+
* The contexts in which an i18n expression can be used.
|
|
9200
|
+
*/
|
|
9201
|
+
var I18nExpressionFor;
|
|
9202
|
+
(function (I18nExpressionFor) {
|
|
9203
|
+
/**
|
|
9204
|
+
* This expression is used as a value (i.e. inside an i18n block).
|
|
9205
|
+
*/
|
|
9206
|
+
I18nExpressionFor[I18nExpressionFor["I18nText"] = 0] = "I18nText";
|
|
9207
|
+
/**
|
|
9208
|
+
* This expression is used in a binding.
|
|
9209
|
+
*/
|
|
9210
|
+
I18nExpressionFor[I18nExpressionFor["I18nAttribute"] = 1] = "I18nAttribute";
|
|
9211
|
+
})(I18nExpressionFor || (I18nExpressionFor = {}));
|
|
9139
9212
|
/**
|
|
9140
9213
|
* Flags that describe what an i18n param value. These determine how the value is serialized into
|
|
9141
9214
|
* the final map.
|
|
@@ -9202,7 +9275,14 @@ var I18nContextKind;
|
|
|
9202
9275
|
(function (I18nContextKind) {
|
|
9203
9276
|
I18nContextKind[I18nContextKind["RootI18n"] = 0] = "RootI18n";
|
|
9204
9277
|
I18nContextKind[I18nContextKind["Icu"] = 1] = "Icu";
|
|
9278
|
+
I18nContextKind[I18nContextKind["Attr"] = 2] = "Attr";
|
|
9205
9279
|
})(I18nContextKind || (I18nContextKind = {}));
|
|
9280
|
+
var TemplateKind;
|
|
9281
|
+
(function (TemplateKind) {
|
|
9282
|
+
TemplateKind[TemplateKind["NgTemplate"] = 0] = "NgTemplate";
|
|
9283
|
+
TemplateKind[TemplateKind["Structural"] = 1] = "Structural";
|
|
9284
|
+
TemplateKind[TemplateKind["Block"] = 2] = "Block";
|
|
9285
|
+
})(TemplateKind || (TemplateKind = {}));
|
|
9206
9286
|
|
|
9207
9287
|
/**
|
|
9208
9288
|
* Marker symbol for `ConsumesSlotOpTrait`.
|
|
@@ -9310,12 +9390,11 @@ const NEW_OP = {
|
|
|
9310
9390
|
/**
|
|
9311
9391
|
* Create an `InterpolationTextOp`.
|
|
9312
9392
|
*/
|
|
9313
|
-
function createInterpolateTextOp(xref, interpolation,
|
|
9393
|
+
function createInterpolateTextOp(xref, interpolation, sourceSpan) {
|
|
9314
9394
|
return {
|
|
9315
9395
|
kind: OpKind.InterpolateText,
|
|
9316
9396
|
target: xref,
|
|
9317
9397
|
interpolation,
|
|
9318
|
-
i18nPlaceholders,
|
|
9319
9398
|
sourceSpan,
|
|
9320
9399
|
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9321
9400
|
...TRAIT_CONSUMES_VARS,
|
|
@@ -9323,15 +9402,19 @@ function createInterpolateTextOp(xref, interpolation, i18nPlaceholders, sourceSp
|
|
|
9323
9402
|
};
|
|
9324
9403
|
}
|
|
9325
9404
|
class Interpolation {
|
|
9326
|
-
constructor(strings, expressions) {
|
|
9405
|
+
constructor(strings, expressions, i18nPlaceholders) {
|
|
9327
9406
|
this.strings = strings;
|
|
9328
9407
|
this.expressions = expressions;
|
|
9408
|
+
this.i18nPlaceholders = i18nPlaceholders;
|
|
9409
|
+
if (i18nPlaceholders.length !== 0 && i18nPlaceholders.length !== expressions.length) {
|
|
9410
|
+
throw new Error(`Expected ${expressions.length} placeholders to match interpolation expression count, but got ${i18nPlaceholders.length}`);
|
|
9411
|
+
}
|
|
9329
9412
|
}
|
|
9330
9413
|
}
|
|
9331
9414
|
/**
|
|
9332
9415
|
* Create a `BindingOp`, not yet transformed into a particular type of binding.
|
|
9333
9416
|
*/
|
|
9334
|
-
function createBindingOp(target, kind, name, expression, unit, securityContext, isTextAttribute,
|
|
9417
|
+
function createBindingOp(target, kind, name, expression, unit, securityContext, isTextAttribute, isStructuralTemplate, i18nContext, sourceSpan) {
|
|
9335
9418
|
return {
|
|
9336
9419
|
kind: OpKind.Binding,
|
|
9337
9420
|
bindingKind: kind,
|
|
@@ -9341,7 +9424,8 @@ function createBindingOp(target, kind, name, expression, unit, securityContext,
|
|
|
9341
9424
|
unit,
|
|
9342
9425
|
securityContext,
|
|
9343
9426
|
isTextAttribute,
|
|
9344
|
-
|
|
9427
|
+
isStructuralTemplate: isStructuralTemplate,
|
|
9428
|
+
i18nContext,
|
|
9345
9429
|
sourceSpan,
|
|
9346
9430
|
...NEW_OP,
|
|
9347
9431
|
};
|
|
@@ -9349,7 +9433,7 @@ function createBindingOp(target, kind, name, expression, unit, securityContext,
|
|
|
9349
9433
|
/**
|
|
9350
9434
|
* Create a `PropertyOp`.
|
|
9351
9435
|
*/
|
|
9352
|
-
function createPropertyOp(target, name, expression, isAnimationTrigger, securityContext,
|
|
9436
|
+
function createPropertyOp(target, name, expression, isAnimationTrigger, securityContext, isStructuralTemplate, i18nContext, sourceSpan) {
|
|
9353
9437
|
return {
|
|
9354
9438
|
kind: OpKind.Property,
|
|
9355
9439
|
target,
|
|
@@ -9358,7 +9442,8 @@ function createPropertyOp(target, name, expression, isAnimationTrigger, security
|
|
|
9358
9442
|
isAnimationTrigger,
|
|
9359
9443
|
securityContext,
|
|
9360
9444
|
sanitizer: null,
|
|
9361
|
-
|
|
9445
|
+
isStructuralTemplate,
|
|
9446
|
+
i18nContext,
|
|
9362
9447
|
sourceSpan,
|
|
9363
9448
|
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9364
9449
|
...TRAIT_CONSUMES_VARS,
|
|
@@ -9423,7 +9508,7 @@ function createClassMapOp(xref, expression, sourceSpan) {
|
|
|
9423
9508
|
/**
|
|
9424
9509
|
* Create an `AttributeOp`.
|
|
9425
9510
|
*/
|
|
9426
|
-
function createAttributeOp(target, name, expression, securityContext, isTextAttribute,
|
|
9511
|
+
function createAttributeOp(target, name, expression, securityContext, isTextAttribute, isStructuralTemplate, i18nContext, sourceSpan) {
|
|
9427
9512
|
return {
|
|
9428
9513
|
kind: OpKind.Attribute,
|
|
9429
9514
|
target,
|
|
@@ -9432,7 +9517,8 @@ function createAttributeOp(target, name, expression, securityContext, isTextAttr
|
|
|
9432
9517
|
securityContext,
|
|
9433
9518
|
sanitizer: null,
|
|
9434
9519
|
isTextAttribute,
|
|
9435
|
-
|
|
9520
|
+
isStructuralTemplate,
|
|
9521
|
+
i18nContext,
|
|
9436
9522
|
sourceSpan,
|
|
9437
9523
|
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9438
9524
|
...TRAIT_CONSUMES_VARS,
|
|
@@ -9493,15 +9579,18 @@ function createDeferWhenOp(target, expr, prefetch, sourceSpan) {
|
|
|
9493
9579
|
/**
|
|
9494
9580
|
* Create an i18n expression op.
|
|
9495
9581
|
*/
|
|
9496
|
-
function createI18nExpressionOp(context, target, handle, expression, i18nPlaceholder, resolutionTime, sourceSpan) {
|
|
9582
|
+
function createI18nExpressionOp(context, target, i18nOwner, handle, expression, i18nPlaceholder, resolutionTime, usage, name, sourceSpan) {
|
|
9497
9583
|
return {
|
|
9498
9584
|
kind: OpKind.I18nExpression,
|
|
9499
9585
|
context,
|
|
9500
9586
|
target,
|
|
9587
|
+
i18nOwner,
|
|
9501
9588
|
handle,
|
|
9502
9589
|
expression,
|
|
9503
9590
|
i18nPlaceholder,
|
|
9504
9591
|
resolutionTime,
|
|
9592
|
+
usage,
|
|
9593
|
+
name,
|
|
9505
9594
|
sourceSpan,
|
|
9506
9595
|
...NEW_OP,
|
|
9507
9596
|
...TRAIT_CONSUMES_VARS,
|
|
@@ -9509,12 +9598,12 @@ function createI18nExpressionOp(context, target, handle, expression, i18nPlaceho
|
|
|
9509
9598
|
};
|
|
9510
9599
|
}
|
|
9511
9600
|
/**
|
|
9512
|
-
*Creates an op to apply i18n expression ops
|
|
9601
|
+
* Creates an op to apply i18n expression ops.
|
|
9513
9602
|
*/
|
|
9514
|
-
function createI18nApplyOp(
|
|
9603
|
+
function createI18nApplyOp(owner, handle, sourceSpan) {
|
|
9515
9604
|
return {
|
|
9516
9605
|
kind: OpKind.I18nApply,
|
|
9517
|
-
|
|
9606
|
+
owner,
|
|
9518
9607
|
handle,
|
|
9519
9608
|
sourceSpan,
|
|
9520
9609
|
...NEW_OP,
|
|
@@ -10318,6 +10407,7 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
10318
10407
|
case OpKind.ProjectionDef:
|
|
10319
10408
|
case OpKind.Template:
|
|
10320
10409
|
case OpKind.Text:
|
|
10410
|
+
case OpKind.I18nAttributes:
|
|
10321
10411
|
// These operations contain no expressions.
|
|
10322
10412
|
break;
|
|
10323
10413
|
default:
|
|
@@ -10338,6 +10428,9 @@ function transformExpressionsInExpression(expr, transform, flags) {
|
|
|
10338
10428
|
expr.lhs = transformExpressionsInExpression(expr.lhs, transform, flags);
|
|
10339
10429
|
expr.rhs = transformExpressionsInExpression(expr.rhs, transform, flags);
|
|
10340
10430
|
}
|
|
10431
|
+
else if (expr instanceof UnaryOperatorExpr) {
|
|
10432
|
+
expr.expr = transformExpressionsInExpression(expr.expr, transform, flags);
|
|
10433
|
+
}
|
|
10341
10434
|
else if (expr instanceof ReadPropExpr) {
|
|
10342
10435
|
expr.receiver = transformExpressionsInExpression(expr.receiver, transform, flags);
|
|
10343
10436
|
}
|
|
@@ -10389,6 +10482,9 @@ function transformExpressionsInExpression(expr, transform, flags) {
|
|
|
10389
10482
|
expr.expressions[i] = transformExpressionsInExpression(expr.expressions[i], transform, flags);
|
|
10390
10483
|
}
|
|
10391
10484
|
}
|
|
10485
|
+
else if (expr instanceof NotExpr) {
|
|
10486
|
+
expr.condition = transformExpressionsInExpression(expr.condition, transform, flags);
|
|
10487
|
+
}
|
|
10392
10488
|
else if (expr instanceof ReadVarExpr || expr instanceof ExternalExpr ||
|
|
10393
10489
|
expr instanceof LiteralExpr) {
|
|
10394
10490
|
// No action for these types.
|
|
@@ -10730,10 +10826,11 @@ function createElementStartOp(tag, xref, namespace, i18nPlaceholder, sourceSpan)
|
|
|
10730
10826
|
/**
|
|
10731
10827
|
* Create a `TemplateOp`.
|
|
10732
10828
|
*/
|
|
10733
|
-
function createTemplateOp(xref, tag, functionNameSuffix, namespace, i18nPlaceholder, sourceSpan) {
|
|
10829
|
+
function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace, i18nPlaceholder, sourceSpan) {
|
|
10734
10830
|
return {
|
|
10735
10831
|
kind: OpKind.Template,
|
|
10736
10832
|
xref,
|
|
10833
|
+
templateKind,
|
|
10737
10834
|
attributes: null,
|
|
10738
10835
|
tag,
|
|
10739
10836
|
handle: new SlotHandle(),
|
|
@@ -10856,14 +10953,15 @@ function createProjectionDefOp(def) {
|
|
|
10856
10953
|
...NEW_OP,
|
|
10857
10954
|
};
|
|
10858
10955
|
}
|
|
10859
|
-
function createProjectionOp(xref, selector, sourceSpan) {
|
|
10956
|
+
function createProjectionOp(xref, selector, i18nPlaceholder, attributes, sourceSpan) {
|
|
10860
10957
|
return {
|
|
10861
10958
|
kind: OpKind.Projection,
|
|
10862
10959
|
xref,
|
|
10863
10960
|
handle: new SlotHandle(),
|
|
10864
10961
|
selector,
|
|
10962
|
+
i18nPlaceholder,
|
|
10865
10963
|
projectionSlotIndex: 0,
|
|
10866
|
-
attributes
|
|
10964
|
+
attributes,
|
|
10867
10965
|
localRefs: [],
|
|
10868
10966
|
sourceSpan,
|
|
10869
10967
|
...NEW_OP,
|
|
@@ -10873,13 +10971,14 @@ function createProjectionOp(xref, selector, sourceSpan) {
|
|
|
10873
10971
|
/**
|
|
10874
10972
|
* Create an `ExtractedAttributeOp`.
|
|
10875
10973
|
*/
|
|
10876
|
-
function createExtractedAttributeOp(target, bindingKind, name, expression) {
|
|
10974
|
+
function createExtractedAttributeOp(target, bindingKind, name, expression, i18nContext) {
|
|
10877
10975
|
return {
|
|
10878
10976
|
kind: OpKind.ExtractedAttribute,
|
|
10879
10977
|
target,
|
|
10880
10978
|
bindingKind,
|
|
10881
10979
|
name,
|
|
10882
10980
|
expression,
|
|
10981
|
+
i18nContext,
|
|
10883
10982
|
...NEW_OP,
|
|
10884
10983
|
};
|
|
10885
10984
|
}
|
|
@@ -10922,10 +11021,11 @@ function createDeferOnOp(defer, trigger, prefetch, sourceSpan) {
|
|
|
10922
11021
|
/**
|
|
10923
11022
|
* Create an `ExtractedMessageOp`.
|
|
10924
11023
|
*/
|
|
10925
|
-
function createI18nMessageOp(xref, i18nBlock, message, messagePlaceholder, params, postprocessingParams, needsPostprocessing) {
|
|
11024
|
+
function createI18nMessageOp(xref, i18nContext, i18nBlock, message, messagePlaceholder, params, postprocessingParams, needsPostprocessing) {
|
|
10926
11025
|
return {
|
|
10927
11026
|
kind: OpKind.I18nMessage,
|
|
10928
11027
|
xref,
|
|
11028
|
+
i18nContext,
|
|
10929
11029
|
i18nBlock,
|
|
10930
11030
|
message,
|
|
10931
11031
|
messagePlaceholder,
|
|
@@ -10988,6 +11088,9 @@ function createIcuEndOp(xref) {
|
|
|
10988
11088
|
};
|
|
10989
11089
|
}
|
|
10990
11090
|
function createI18nContextOp(contextKind, xref, i18nBlock, message, sourceSpan) {
|
|
11091
|
+
if (i18nBlock === null && contextKind !== I18nContextKind.Attr) {
|
|
11092
|
+
throw new Error('AssertionError: i18nBlock must be provided for non-attribute contexts.');
|
|
11093
|
+
}
|
|
10991
11094
|
return {
|
|
10992
11095
|
kind: OpKind.I18nContext,
|
|
10993
11096
|
contextKind,
|
|
@@ -11000,6 +11103,17 @@ function createI18nContextOp(contextKind, xref, i18nBlock, message, sourceSpan)
|
|
|
11000
11103
|
...NEW_OP,
|
|
11001
11104
|
};
|
|
11002
11105
|
}
|
|
11106
|
+
function createI18nAttributesOp(xref, handle, target) {
|
|
11107
|
+
return {
|
|
11108
|
+
kind: OpKind.I18nAttributes,
|
|
11109
|
+
xref,
|
|
11110
|
+
handle,
|
|
11111
|
+
target,
|
|
11112
|
+
i18nAttributesConfig: null,
|
|
11113
|
+
...NEW_OP,
|
|
11114
|
+
...TRAIT_CONSUMES_SLOT,
|
|
11115
|
+
};
|
|
11116
|
+
}
|
|
11003
11117
|
function literalOrArrayLiteral$1(value) {
|
|
11004
11118
|
if (Array.isArray(value)) {
|
|
11005
11119
|
return literalArr(value.map(literalOrArrayLiteral$1));
|
|
@@ -11007,12 +11121,13 @@ function literalOrArrayLiteral$1(value) {
|
|
|
11007
11121
|
return literal(value, INFERRED_TYPE);
|
|
11008
11122
|
}
|
|
11009
11123
|
|
|
11010
|
-
function createHostPropertyOp(name, expression, isAnimationTrigger, sourceSpan) {
|
|
11124
|
+
function createHostPropertyOp(name, expression, isAnimationTrigger, i18nContext, sourceSpan) {
|
|
11011
11125
|
return {
|
|
11012
11126
|
kind: OpKind.HostProperty,
|
|
11013
11127
|
name,
|
|
11014
11128
|
expression,
|
|
11015
11129
|
isAnimationTrigger,
|
|
11130
|
+
i18nContext,
|
|
11016
11131
|
sourceSpan,
|
|
11017
11132
|
...TRAIT_CONSUMES_VARS,
|
|
11018
11133
|
...NEW_OP,
|
|
@@ -11249,7 +11364,7 @@ function applyI18nExpressions(job) {
|
|
|
11249
11364
|
// Only add apply after expressions that are not followed by more expressions.
|
|
11250
11365
|
if (op.kind === OpKind.I18nExpression && needsApplication(i18nContexts, op)) {
|
|
11251
11366
|
// TODO: what should be the source span for the apply op?
|
|
11252
|
-
OpList.insertAfter(createI18nApplyOp(op.
|
|
11367
|
+
OpList.insertAfter(createI18nApplyOp(op.i18nOwner, op.handle, null), op);
|
|
11253
11368
|
}
|
|
11254
11369
|
}
|
|
11255
11370
|
}
|
|
@@ -11262,17 +11377,34 @@ function needsApplication(i18nContexts, op) {
|
|
|
11262
11377
|
if (op.next?.kind !== OpKind.I18nExpression) {
|
|
11263
11378
|
return true;
|
|
11264
11379
|
}
|
|
11265
|
-
// If the next op is an expression targeting a different i18n block, we need to apply.
|
|
11266
11380
|
const context = i18nContexts.get(op.context);
|
|
11267
11381
|
const nextContext = i18nContexts.get(op.next.context);
|
|
11268
|
-
if (context
|
|
11382
|
+
if (context === undefined) {
|
|
11383
|
+
throw new Error('AssertionError: expected an I18nContextOp to exist for the I18nExpressionOp\'s context');
|
|
11384
|
+
}
|
|
11385
|
+
if (nextContext === undefined) {
|
|
11386
|
+
throw new Error('AssertionError: expected an I18nContextOp to exist for the next I18nExpressionOp\'s context');
|
|
11387
|
+
}
|
|
11388
|
+
// If the next op is an expression targeting a different i18n block (or different element, in the
|
|
11389
|
+
// case of i18n attributes), we need to apply.
|
|
11390
|
+
// First, handle the case of i18n blocks.
|
|
11391
|
+
if (context.i18nBlock !== null) {
|
|
11392
|
+
// This is a block context. Compare the blocks.
|
|
11393
|
+
if (context.i18nBlock !== nextContext.i18nBlock) {
|
|
11394
|
+
return true;
|
|
11395
|
+
}
|
|
11396
|
+
return false;
|
|
11397
|
+
}
|
|
11398
|
+
// Second, handle the case of i18n attributes.
|
|
11399
|
+
if (op.i18nOwner !== op.next.i18nOwner) {
|
|
11269
11400
|
return true;
|
|
11270
11401
|
}
|
|
11271
11402
|
return false;
|
|
11272
11403
|
}
|
|
11273
11404
|
|
|
11274
11405
|
/**
|
|
11275
|
-
* Updates i18n expression ops to
|
|
11406
|
+
* Updates i18n expression ops to target the last slot in their owning i18n block, and moves them
|
|
11407
|
+
* after the last update instruction that depends on that slot.
|
|
11276
11408
|
*/
|
|
11277
11409
|
function assignI18nSlotDependencies(job) {
|
|
11278
11410
|
const i18nLastSlotConsumers = new Map();
|
|
@@ -11289,17 +11421,54 @@ function assignI18nSlotDependencies(job) {
|
|
|
11289
11421
|
currentI18nOp = op;
|
|
11290
11422
|
break;
|
|
11291
11423
|
case OpKind.I18nEnd:
|
|
11424
|
+
if (currentI18nOp === null) {
|
|
11425
|
+
throw new Error('AssertionError: Expected an active I18n block while calculating last slot consumers');
|
|
11426
|
+
}
|
|
11427
|
+
if (lastSlotConsumer === null) {
|
|
11428
|
+
throw new Error('AssertionError: Expected a last slot consumer while calculating last slot consumers');
|
|
11429
|
+
}
|
|
11292
11430
|
i18nLastSlotConsumers.set(currentI18nOp.xref, lastSlotConsumer);
|
|
11293
11431
|
currentI18nOp = null;
|
|
11294
11432
|
break;
|
|
11295
11433
|
}
|
|
11296
11434
|
}
|
|
11297
|
-
//
|
|
11435
|
+
// Expresions that are currently being moved.
|
|
11436
|
+
let opsToMove = [];
|
|
11437
|
+
// Previously we found the last slot-consuming create mode op in the i18n block. That op will be
|
|
11438
|
+
// the new target for any moved i18n expresion inside the i18n block, and that op's slot is
|
|
11439
|
+
// stored here.
|
|
11440
|
+
let moveAfterTarget = null;
|
|
11441
|
+
// This is the last target in the create IR that we saw during iteration. Eventally, it will be
|
|
11442
|
+
// equal to moveAfterTarget. But wait! We need to find the *last* such op whose target is equal
|
|
11443
|
+
// to `moveAfterTarget`.
|
|
11444
|
+
let previousTarget = null;
|
|
11298
11445
|
for (const op of unit.update) {
|
|
11299
|
-
if (op
|
|
11300
|
-
op
|
|
11446
|
+
if (hasDependsOnSlotContextTrait(op)) {
|
|
11447
|
+
// We've found an op that depends on another slot other than the one that we want to move
|
|
11448
|
+
// the expressions to, after previously having seen the one we want to move to.
|
|
11449
|
+
if (moveAfterTarget !== null && previousTarget === moveAfterTarget &&
|
|
11450
|
+
op.target !== previousTarget) {
|
|
11451
|
+
OpList.insertBefore(opsToMove, op);
|
|
11452
|
+
moveAfterTarget = null;
|
|
11453
|
+
opsToMove = [];
|
|
11454
|
+
}
|
|
11455
|
+
previousTarget = op.target;
|
|
11456
|
+
}
|
|
11457
|
+
if (op.kind === OpKind.I18nExpression && op.usage === I18nExpressionFor.I18nText) {
|
|
11458
|
+
// This is an I18nExpressionOps that is used for text (not attributes).
|
|
11459
|
+
OpList.remove(op);
|
|
11460
|
+
opsToMove.push(op);
|
|
11461
|
+
const target = i18nLastSlotConsumers.get(op.i18nOwner);
|
|
11462
|
+
if (target === undefined) {
|
|
11463
|
+
throw new Error('AssertionError: Expected to find a last slot consumer for an I18nExpressionOp');
|
|
11464
|
+
}
|
|
11465
|
+
op.target = target;
|
|
11466
|
+
moveAfterTarget = op.target;
|
|
11301
11467
|
}
|
|
11302
11468
|
}
|
|
11469
|
+
if (moveAfterTarget !== null) {
|
|
11470
|
+
unit.update.push(opsToMove);
|
|
11471
|
+
}
|
|
11303
11472
|
}
|
|
11304
11473
|
}
|
|
11305
11474
|
|
|
@@ -11331,22 +11500,36 @@ function extractAttributes(job) {
|
|
|
11331
11500
|
break;
|
|
11332
11501
|
case OpKind.Property:
|
|
11333
11502
|
if (!op.isAnimationTrigger) {
|
|
11334
|
-
|
|
11503
|
+
let bindingKind;
|
|
11504
|
+
if (op.i18nContext !== null) {
|
|
11505
|
+
// If the binding has an i18n context, it is an i18n attribute, and should have that
|
|
11506
|
+
// kind in the consts array.
|
|
11507
|
+
bindingKind = BindingKind.I18n;
|
|
11508
|
+
}
|
|
11509
|
+
else if (op.isStructuralTemplate) {
|
|
11510
|
+
// TODO: How do i18n attributes on templates work?!
|
|
11511
|
+
bindingKind = BindingKind.Template;
|
|
11512
|
+
}
|
|
11513
|
+
else {
|
|
11514
|
+
bindingKind = BindingKind.Property;
|
|
11515
|
+
}
|
|
11516
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, bindingKind, op.name, null, null), lookupElement$2(elements, op.target));
|
|
11335
11517
|
}
|
|
11336
11518
|
break;
|
|
11337
11519
|
case OpKind.StyleProp:
|
|
11338
11520
|
case OpKind.ClassProp:
|
|
11521
|
+
// TODO: Can style or class bindings be i18n attributes?
|
|
11339
11522
|
// The old compiler treated empty style bindings as regular bindings for the purpose of
|
|
11340
11523
|
// directive matching. That behavior is incorrect, but we emulate it in compatibility
|
|
11341
11524
|
// mode.
|
|
11342
11525
|
if (unit.job.compatibility === CompatibilityMode.TemplateDefinitionBuilder &&
|
|
11343
11526
|
op.expression instanceof EmptyExpr) {
|
|
11344
|
-
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.Property, op.name, null), lookupElement$2(elements, op.target));
|
|
11527
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.Property, op.name, null, null), lookupElement$2(elements, op.target));
|
|
11345
11528
|
}
|
|
11346
11529
|
break;
|
|
11347
11530
|
case OpKind.Listener:
|
|
11348
11531
|
if (!op.isAnimationListener) {
|
|
11349
|
-
const extractedAttributeOp = createExtractedAttributeOp(op.target, BindingKind.Property, op.name, null);
|
|
11532
|
+
const extractedAttributeOp = createExtractedAttributeOp(op.target, BindingKind.Property, op.name, null, null);
|
|
11350
11533
|
if (job.kind === CompilationJobKind.Host) {
|
|
11351
11534
|
// This attribute will apply to the enclosing host binding compilation unit, so order
|
|
11352
11535
|
// doesn't matter.
|
|
@@ -11395,7 +11578,7 @@ function extractAttributeOp(unit, op, elements) {
|
|
|
11395
11578
|
}
|
|
11396
11579
|
}
|
|
11397
11580
|
if (extractable) {
|
|
11398
|
-
const extractedAttributeOp = createExtractedAttributeOp(op.target, op.
|
|
11581
|
+
const extractedAttributeOp = createExtractedAttributeOp(op.target, op.isStructuralTemplate ? BindingKind.Template : BindingKind.Attribute, op.name, op.expression, op.i18nContext);
|
|
11399
11582
|
if (unit.job.kind === CompilationJobKind.Host) {
|
|
11400
11583
|
// This attribute will apply to the enclosing host binding compilation unit, so order doesn't
|
|
11401
11584
|
// matter.
|
|
@@ -11442,16 +11625,16 @@ function specializeBindings(job) {
|
|
|
11442
11625
|
target.nonBindable = true;
|
|
11443
11626
|
}
|
|
11444
11627
|
else {
|
|
11445
|
-
OpList.replace(op, createAttributeOp(op.target, op.name, op.expression, op.securityContext, op.isTextAttribute, op.
|
|
11628
|
+
OpList.replace(op, createAttributeOp(op.target, op.name, op.expression, op.securityContext, op.isTextAttribute, op.isStructuralTemplate, op.i18nContext, op.sourceSpan));
|
|
11446
11629
|
}
|
|
11447
11630
|
break;
|
|
11448
11631
|
case BindingKind.Property:
|
|
11449
11632
|
case BindingKind.Animation:
|
|
11450
11633
|
if (job.kind === CompilationJobKind.Host) {
|
|
11451
|
-
OpList.replace(op, createHostPropertyOp(op.name, op.expression, op.bindingKind === BindingKind.Animation, op.sourceSpan));
|
|
11634
|
+
OpList.replace(op, createHostPropertyOp(op.name, op.expression, op.bindingKind === BindingKind.Animation, op.i18nContext, op.sourceSpan));
|
|
11452
11635
|
}
|
|
11453
11636
|
else {
|
|
11454
|
-
OpList.replace(op, createPropertyOp(op.target, op.name, op.expression, op.bindingKind === BindingKind.Animation, op.securityContext, op.
|
|
11637
|
+
OpList.replace(op, createPropertyOp(op.target, op.name, op.expression, op.bindingKind === BindingKind.Animation, op.securityContext, op.isStructuralTemplate, op.i18nContext, op.sourceSpan));
|
|
11455
11638
|
}
|
|
11456
11639
|
break;
|
|
11457
11640
|
case BindingKind.I18n:
|
|
@@ -11628,41 +11811,6 @@ function generateConditionalExpressions(job) {
|
|
|
11628
11811
|
}
|
|
11629
11812
|
}
|
|
11630
11813
|
|
|
11631
|
-
var TagContentType;
|
|
11632
|
-
(function (TagContentType) {
|
|
11633
|
-
TagContentType[TagContentType["RAW_TEXT"] = 0] = "RAW_TEXT";
|
|
11634
|
-
TagContentType[TagContentType["ESCAPABLE_RAW_TEXT"] = 1] = "ESCAPABLE_RAW_TEXT";
|
|
11635
|
-
TagContentType[TagContentType["PARSABLE_DATA"] = 2] = "PARSABLE_DATA";
|
|
11636
|
-
})(TagContentType || (TagContentType = {}));
|
|
11637
|
-
function splitNsName(elementName) {
|
|
11638
|
-
if (elementName[0] != ':') {
|
|
11639
|
-
return [null, elementName];
|
|
11640
|
-
}
|
|
11641
|
-
const colonIndex = elementName.indexOf(':', 1);
|
|
11642
|
-
if (colonIndex === -1) {
|
|
11643
|
-
throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
|
|
11644
|
-
}
|
|
11645
|
-
return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
|
|
11646
|
-
}
|
|
11647
|
-
// `<ng-container>` tags work the same regardless the namespace
|
|
11648
|
-
function isNgContainer(tagName) {
|
|
11649
|
-
return splitNsName(tagName)[1] === 'ng-container';
|
|
11650
|
-
}
|
|
11651
|
-
// `<ng-content>` tags work the same regardless the namespace
|
|
11652
|
-
function isNgContent(tagName) {
|
|
11653
|
-
return splitNsName(tagName)[1] === 'ng-content';
|
|
11654
|
-
}
|
|
11655
|
-
// `<ng-template>` tags work the same regardless the namespace
|
|
11656
|
-
function isNgTemplate(tagName) {
|
|
11657
|
-
return splitNsName(tagName)[1] === 'ng-template';
|
|
11658
|
-
}
|
|
11659
|
-
function getNsPrefix(fullName) {
|
|
11660
|
-
return fullName === null ? null : splitNsName(fullName)[0];
|
|
11661
|
-
}
|
|
11662
|
-
function mergeNsAndName(prefix, localName) {
|
|
11663
|
-
return prefix ? `:${prefix}:${localName}` : localName;
|
|
11664
|
-
}
|
|
11665
|
-
|
|
11666
11814
|
const BINARY_OPERATORS = new Map([
|
|
11667
11815
|
['&&', BinaryOperator.And],
|
|
11668
11816
|
['>', BinaryOperator.Bigger],
|
|
@@ -11807,7 +11955,7 @@ class ElementAttributes {
|
|
|
11807
11955
|
array.push(...getAttributeNameLiterals$1(name));
|
|
11808
11956
|
if (kind === BindingKind.Attribute || kind === BindingKind.StyleProperty) {
|
|
11809
11957
|
if (value === null) {
|
|
11810
|
-
throw Error('Attribute & style element attributes must have a value');
|
|
11958
|
+
throw Error('Attribute, i18n attribute, & style element attributes must have a value');
|
|
11811
11959
|
}
|
|
11812
11960
|
array.push(value);
|
|
11813
11961
|
}
|
|
@@ -11861,6 +12009,50 @@ function serializeAttributes({ attributes, bindings, classes, i18n, projectAs, s
|
|
|
11861
12009
|
return literalArr(attrArray);
|
|
11862
12010
|
}
|
|
11863
12011
|
|
|
12012
|
+
/**
|
|
12013
|
+
* Some binding instructions in the update block may actually correspond to i18n bindings. In that
|
|
12014
|
+
* case, they should be replaced with i18nExp instructions for the dynamic portions.
|
|
12015
|
+
*/
|
|
12016
|
+
function convertI18nBindings(job) {
|
|
12017
|
+
const i18nAttributesByElem = new Map();
|
|
12018
|
+
for (const unit of job.units) {
|
|
12019
|
+
for (const op of unit.create) {
|
|
12020
|
+
if (op.kind === OpKind.I18nAttributes) {
|
|
12021
|
+
i18nAttributesByElem.set(op.target, op);
|
|
12022
|
+
}
|
|
12023
|
+
}
|
|
12024
|
+
for (const op of unit.update) {
|
|
12025
|
+
switch (op.kind) {
|
|
12026
|
+
case OpKind.Property:
|
|
12027
|
+
case OpKind.Attribute:
|
|
12028
|
+
if (op.i18nContext === null) {
|
|
12029
|
+
continue;
|
|
12030
|
+
}
|
|
12031
|
+
if (!(op.expression instanceof Interpolation)) {
|
|
12032
|
+
continue;
|
|
12033
|
+
}
|
|
12034
|
+
const i18nAttributesForElem = i18nAttributesByElem.get(op.target);
|
|
12035
|
+
if (i18nAttributesForElem === undefined) {
|
|
12036
|
+
throw new Error('AssertionError: An i18n attribute binding instruction requires the owning element to have an I18nAttributes create instruction');
|
|
12037
|
+
}
|
|
12038
|
+
if (i18nAttributesForElem.target !== op.target) {
|
|
12039
|
+
throw new Error('AssertionError: Expected i18nAttributes target element to match binding target element');
|
|
12040
|
+
}
|
|
12041
|
+
const ops = [];
|
|
12042
|
+
for (let i = 0; i < op.expression.expressions.length; i++) {
|
|
12043
|
+
const expr = op.expression.expressions[i];
|
|
12044
|
+
if (op.expression.i18nPlaceholders.length !== op.expression.expressions.length) {
|
|
12045
|
+
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`);
|
|
12046
|
+
}
|
|
12047
|
+
ops.push(createI18nExpressionOp(op.i18nContext, i18nAttributesForElem.target, i18nAttributesForElem.xref, i18nAttributesForElem.handle, expr, op.expression.i18nPlaceholders[i], I18nParamResolutionTime.Creation, I18nExpressionFor.I18nAttribute, op.name, op.sourceSpan));
|
|
12048
|
+
}
|
|
12049
|
+
OpList.replaceWithMany(op, ops);
|
|
12050
|
+
break;
|
|
12051
|
+
}
|
|
12052
|
+
}
|
|
12053
|
+
}
|
|
12054
|
+
}
|
|
12055
|
+
|
|
11864
12056
|
/**
|
|
11865
12057
|
* Create extracted deps functions for defer ops.
|
|
11866
12058
|
*/
|
|
@@ -12304,7 +12496,7 @@ function ternaryTransform(e) {
|
|
|
12304
12496
|
/**
|
|
12305
12497
|
* The escape sequence used indicate message param values.
|
|
12306
12498
|
*/
|
|
12307
|
-
const ESCAPE = '\uFFFD';
|
|
12499
|
+
const ESCAPE$1 = '\uFFFD';
|
|
12308
12500
|
/**
|
|
12309
12501
|
* Marker used to indicate an element tag.
|
|
12310
12502
|
*/
|
|
@@ -12353,6 +12545,18 @@ function extractI18nMessages(job) {
|
|
|
12353
12545
|
}
|
|
12354
12546
|
}
|
|
12355
12547
|
}
|
|
12548
|
+
// TODO: Miles and I think that contexts have a 1-to-1 correspondence with extracted messages, so
|
|
12549
|
+
// this phase can probably be simplified.
|
|
12550
|
+
// Extract messages from contexts of i18n attributes.
|
|
12551
|
+
for (const unit of job.units) {
|
|
12552
|
+
for (const op of unit.create) {
|
|
12553
|
+
if (op.kind !== OpKind.I18nContext || op.contextKind !== I18nContextKind.Attr) {
|
|
12554
|
+
continue;
|
|
12555
|
+
}
|
|
12556
|
+
const i18nMessageOp = createI18nMessage(job, op);
|
|
12557
|
+
unit.create.push(i18nMessageOp);
|
|
12558
|
+
}
|
|
12559
|
+
}
|
|
12356
12560
|
// Extract messages from root i18n blocks.
|
|
12357
12561
|
const i18nBlockMessages = new Map();
|
|
12358
12562
|
for (const unit of job.units) {
|
|
@@ -12377,6 +12581,9 @@ function extractI18nMessages(job) {
|
|
|
12377
12581
|
}
|
|
12378
12582
|
const i18nContext = i18nContexts.get(op.context);
|
|
12379
12583
|
if (i18nContext.contextKind === I18nContextKind.Icu) {
|
|
12584
|
+
if (i18nContext.i18nBlock === null) {
|
|
12585
|
+
throw Error('ICU context should have its i18n block set.');
|
|
12586
|
+
}
|
|
12380
12587
|
const subMessage = createI18nMessage(job, i18nContext, op.messagePlaceholder);
|
|
12381
12588
|
unit.create.push(subMessage);
|
|
12382
12589
|
const rootI18nId = i18nBlocks.get(i18nContext.i18nBlock).root;
|
|
@@ -12396,119 +12603,86 @@ function extractI18nMessages(job) {
|
|
|
12396
12603
|
* Create an i18n message op from an i18n context op.
|
|
12397
12604
|
*/
|
|
12398
12605
|
function createI18nMessage(job, context, messagePlaceholder) {
|
|
12399
|
-
let
|
|
12400
|
-
const
|
|
12401
|
-
needsPostprocessing
|
|
12402
|
-
|
|
12606
|
+
let formattedParams = formatParams(context.params);
|
|
12607
|
+
const formattedPostprocessingParams = formatParams(context.postprocessingParams);
|
|
12608
|
+
let needsPostprocessing = formattedPostprocessingParams.size > 0;
|
|
12609
|
+
for (const values of context.params.values()) {
|
|
12610
|
+
if (values.length > 1) {
|
|
12611
|
+
needsPostprocessing = true;
|
|
12612
|
+
}
|
|
12613
|
+
}
|
|
12614
|
+
return createI18nMessageOp(job.allocateXrefId(), context.xref, context.i18nBlock, context.message, messagePlaceholder ?? null, formattedParams, formattedPostprocessingParams, needsPostprocessing);
|
|
12403
12615
|
}
|
|
12404
12616
|
/**
|
|
12405
12617
|
* Formats a map of `I18nParamValue[]` values into a map of `Expression` values.
|
|
12406
|
-
* @return A tuple of the formatted params and a boolean indicating whether postprocessing is needed
|
|
12407
|
-
* for any of the params
|
|
12408
12618
|
*/
|
|
12409
12619
|
function formatParams(params) {
|
|
12410
12620
|
const formattedParams = new Map();
|
|
12411
|
-
let needsPostprocessing = false;
|
|
12412
12621
|
for (const [placeholder, placeholderValues] of params) {
|
|
12413
|
-
const
|
|
12414
|
-
needsPostprocessing ||= paramNeedsPostprocessing;
|
|
12622
|
+
const serializedValues = formatParamValues(placeholderValues);
|
|
12415
12623
|
if (serializedValues !== null) {
|
|
12416
12624
|
formattedParams.set(placeholder, literal(serializedValues));
|
|
12417
12625
|
}
|
|
12418
12626
|
}
|
|
12419
|
-
return
|
|
12627
|
+
return formattedParams;
|
|
12420
12628
|
}
|
|
12421
12629
|
/**
|
|
12422
12630
|
* Formats an `I18nParamValue[]` into a string (or null for empty array).
|
|
12423
|
-
* @return A tuple of the formatted value and a boolean indicating whether postprocessing is needed
|
|
12424
|
-
* for the value
|
|
12425
12631
|
*/
|
|
12426
12632
|
function formatParamValues(values) {
|
|
12427
12633
|
if (values.length === 0) {
|
|
12428
|
-
return
|
|
12634
|
+
return null;
|
|
12429
12635
|
}
|
|
12430
|
-
collapseElementTemplatePairs(values);
|
|
12431
12636
|
const serializedValues = values.map(value => formatValue(value));
|
|
12432
12637
|
return serializedValues.length === 1 ?
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
}
|
|
12436
|
-
/**
|
|
12437
|
-
* Collapses element/template pairs that refer to the same subTemplateIndex, i.e. elements and
|
|
12438
|
-
* templates that refer to the same element instance.
|
|
12439
|
-
*
|
|
12440
|
-
* This accounts for the case of a structural directive inside an i18n block, e.g.:
|
|
12441
|
-
* ```
|
|
12442
|
-
* <div i18n>
|
|
12443
|
-
* <div *ngIf="condition">
|
|
12444
|
-
* </div>
|
|
12445
|
-
* ```
|
|
12446
|
-
*
|
|
12447
|
-
* In this case, both the element start and template start placeholders are the same,
|
|
12448
|
-
* and we collapse them down into a single compound placeholder value. Rather than produce
|
|
12449
|
-
* `[\uFFFD#1:1\uFFFD|\uFFFD*2:1\uFFFD]`, we want to produce `\uFFFD#1:1\uFFFD\uFFFD*2:1\uFFFD`,
|
|
12450
|
-
* likewise for the closing of the element/template.
|
|
12451
|
-
*/
|
|
12452
|
-
function collapseElementTemplatePairs(values) {
|
|
12453
|
-
// Record the indicies of element and template values in the values array by subTemplateIndex.
|
|
12454
|
-
const valueIndiciesBySubTemplateIndex = new Map();
|
|
12455
|
-
for (let i = 0; i < values.length; i++) {
|
|
12456
|
-
const value = values[i];
|
|
12457
|
-
if (value.subTemplateIndex !== null &&
|
|
12458
|
-
(value.flags & (I18nParamValueFlags.ElementTag | I18nParamValueFlags.TemplateTag))) {
|
|
12459
|
-
const valueIndicies = valueIndiciesBySubTemplateIndex.get(value.subTemplateIndex) ?? [];
|
|
12460
|
-
valueIndicies.push(i);
|
|
12461
|
-
valueIndiciesBySubTemplateIndex.set(value.subTemplateIndex, valueIndicies);
|
|
12462
|
-
}
|
|
12463
|
-
}
|
|
12464
|
-
// For each subTemplateIndex, check if any values can be collapsed.
|
|
12465
|
-
for (const [subTemplateIndex, valueIndicies] of valueIndiciesBySubTemplateIndex) {
|
|
12466
|
-
if (valueIndicies.length > 1) {
|
|
12467
|
-
const elementIndex = valueIndicies.find(index => values[index].flags & I18nParamValueFlags.ElementTag);
|
|
12468
|
-
const templateIndex = valueIndicies.find(index => values[index].flags & I18nParamValueFlags.TemplateTag);
|
|
12469
|
-
// If the values list contains both an element and template value, we can collapse.
|
|
12470
|
-
if (elementIndex !== undefined && templateIndex !== undefined) {
|
|
12471
|
-
const elementValue = values[elementIndex];
|
|
12472
|
-
const templateValue = values[templateIndex];
|
|
12473
|
-
// To match the TemplateDefinitionBuilder output, flip the order depending on whether the
|
|
12474
|
-
// values represent a closing or opening tag (or both).
|
|
12475
|
-
// TODO(mmalerba): Figure out if this makes a difference in terms of either functionality,
|
|
12476
|
-
// or the resulting message ID. If not, we can remove the special-casing in the future.
|
|
12477
|
-
let compundValue;
|
|
12478
|
-
if ((elementValue.flags & I18nParamValueFlags.OpenTag) &&
|
|
12479
|
-
(elementValue.flags & I18nParamValueFlags.CloseTag)) {
|
|
12480
|
-
// TODO(mmalerba): Is this a TDB bug? I don't understand why it would put the template
|
|
12481
|
-
// value twice.
|
|
12482
|
-
compundValue = `${formatValue(templateValue)}${formatValue(elementValue)}${formatValue(templateValue)}`;
|
|
12483
|
-
}
|
|
12484
|
-
else if (elementValue.flags & I18nParamValueFlags.OpenTag) {
|
|
12485
|
-
compundValue = `${formatValue(templateValue)}${formatValue(elementValue)}`;
|
|
12486
|
-
}
|
|
12487
|
-
else {
|
|
12488
|
-
compundValue = `${formatValue(elementValue)}${formatValue(templateValue)}`;
|
|
12489
|
-
}
|
|
12490
|
-
// Replace the element value with the combined value.
|
|
12491
|
-
values.splice(elementIndex, 1, { value: compundValue, subTemplateIndex, flags: I18nParamValueFlags.None });
|
|
12492
|
-
// Replace the template value with null to preserve the indicies we calculated earlier.
|
|
12493
|
-
values.splice(templateIndex, 1, null);
|
|
12494
|
-
}
|
|
12495
|
-
}
|
|
12496
|
-
}
|
|
12497
|
-
// Strip out any nulled out values we introduced above.
|
|
12498
|
-
for (let i = values.length - 1; i >= 0; i--) {
|
|
12499
|
-
if (values[i] === null) {
|
|
12500
|
-
values.splice(i, 1);
|
|
12501
|
-
}
|
|
12502
|
-
}
|
|
12638
|
+
serializedValues[0] :
|
|
12639
|
+
`${LIST_START_MARKER}${serializedValues.join(LIST_DELIMITER)}${LIST_END_MARKER}`;
|
|
12503
12640
|
}
|
|
12504
12641
|
/**
|
|
12505
12642
|
* Formats a single `I18nParamValue` into a string
|
|
12506
12643
|
*/
|
|
12507
12644
|
function formatValue(value) {
|
|
12645
|
+
// Element tags with a structural directive use a special form that concatenates the element and
|
|
12646
|
+
// template values.
|
|
12647
|
+
if ((value.flags & I18nParamValueFlags.ElementTag) &&
|
|
12648
|
+
(value.flags & I18nParamValueFlags.TemplateTag)) {
|
|
12649
|
+
if (typeof value.value !== 'object') {
|
|
12650
|
+
throw Error('AssertionError: Expected i18n param value to have an element and template slot');
|
|
12651
|
+
}
|
|
12652
|
+
const elementValue = formatValue({
|
|
12653
|
+
...value,
|
|
12654
|
+
value: value.value.element,
|
|
12655
|
+
flags: value.flags & ~I18nParamValueFlags.TemplateTag
|
|
12656
|
+
});
|
|
12657
|
+
const templateValue = formatValue({
|
|
12658
|
+
...value,
|
|
12659
|
+
value: value.value.template,
|
|
12660
|
+
flags: value.flags & ~I18nParamValueFlags.ElementTag
|
|
12661
|
+
});
|
|
12662
|
+
// TODO(mmalerba): This is likely a bug in TemplateDefinitionBuilder, we should not need to
|
|
12663
|
+
// record the template value twice. For now I'm re-implementing the behavior here to keep the
|
|
12664
|
+
// output consistent with TemplateDefinitionBuilder.
|
|
12665
|
+
if ((value.flags & I18nParamValueFlags.OpenTag) &&
|
|
12666
|
+
(value.flags & I18nParamValueFlags.CloseTag)) {
|
|
12667
|
+
return `${templateValue}${elementValue}${templateValue}`;
|
|
12668
|
+
}
|
|
12669
|
+
// To match the TemplateDefinitionBuilder output, flip the order depending on whether the
|
|
12670
|
+
// values represent a closing or opening tag (or both).
|
|
12671
|
+
// TODO(mmalerba): Figure out if this makes a difference in terms of either functionality,
|
|
12672
|
+
// or the resulting message ID. If not, we can remove the special-casing in the future.
|
|
12673
|
+
return value.flags & I18nParamValueFlags.CloseTag ? `${elementValue}${templateValue}` :
|
|
12674
|
+
`${templateValue}${elementValue}`;
|
|
12675
|
+
}
|
|
12676
|
+
// Self-closing tags use a special form that concatenates the start and close tag values.
|
|
12677
|
+
if ((value.flags & I18nParamValueFlags.OpenTag) &&
|
|
12678
|
+
(value.flags & I18nParamValueFlags.CloseTag)) {
|
|
12679
|
+
return `${formatValue({ ...value, flags: value.flags & ~I18nParamValueFlags.CloseTag })}${formatValue({ ...value, flags: value.flags & ~I18nParamValueFlags.OpenTag })}`;
|
|
12680
|
+
}
|
|
12508
12681
|
// If there are no special flags, just return the raw value.
|
|
12509
12682
|
if (value.flags === I18nParamValueFlags.None) {
|
|
12510
12683
|
return `${value.value}`;
|
|
12511
12684
|
}
|
|
12685
|
+
// Encode the remaining flags as part of the value.
|
|
12512
12686
|
let tagMarker = '';
|
|
12513
12687
|
let closeMarker = '';
|
|
12514
12688
|
if (value.flags & I18nParamValueFlags.ElementTag) {
|
|
@@ -12521,12 +12695,7 @@ function formatValue(value) {
|
|
|
12521
12695
|
closeMarker = value.flags & I18nParamValueFlags.CloseTag ? TAG_CLOSE_MARKER : '';
|
|
12522
12696
|
}
|
|
12523
12697
|
const context = value.subTemplateIndex === null ? '' : `${CONTEXT_MARKER}${value.subTemplateIndex}`;
|
|
12524
|
-
|
|
12525
|
-
if ((value.flags & I18nParamValueFlags.OpenTag) &&
|
|
12526
|
-
(value.flags & I18nParamValueFlags.CloseTag)) {
|
|
12527
|
-
return `${ESCAPE}${tagMarker}${value.value}${context}${ESCAPE}${ESCAPE}${closeMarker}${tagMarker}${value.value}${context}${ESCAPE}`;
|
|
12528
|
-
}
|
|
12529
|
-
return `${ESCAPE}${closeMarker}${tagMarker}${value.value}${context}${ESCAPE}`;
|
|
12698
|
+
return `${ESCAPE$1}${closeMarker}${tagMarker}${value.value}${context}${ESCAPE$1}`;
|
|
12530
12699
|
}
|
|
12531
12700
|
|
|
12532
12701
|
/**
|
|
@@ -12560,7 +12729,7 @@ function generateAdvance(job) {
|
|
|
12560
12729
|
else if (!slotMap.has(op.target)) {
|
|
12561
12730
|
// We expect ops that _do_ depend on the slot counter to point at declarations that exist in
|
|
12562
12731
|
// the `slotMap`.
|
|
12563
|
-
throw new Error(`AssertionError: reference to unknown slot for
|
|
12732
|
+
throw new Error(`AssertionError: reference to unknown slot for target ${op.target}`);
|
|
12564
12733
|
}
|
|
12565
12734
|
const slot = slotMap.get(op.target);
|
|
12566
12735
|
// Does the slot counter need to be adjusted?
|
|
@@ -19770,35 +19939,132 @@ const NG_I18N_CLOSURE_MODE$1 = 'ngI18nClosureMode';
|
|
|
19770
19939
|
* considers variables like `I18N_0` as constants and throws an error when their value changes.
|
|
19771
19940
|
*/
|
|
19772
19941
|
const TRANSLATION_VAR_PREFIX = 'i18n_';
|
|
19942
|
+
/** Prefix of ICU expressions for post processing */
|
|
19943
|
+
const I18N_ICU_MAPPING_PREFIX = 'I18N_EXP_';
|
|
19944
|
+
/**
|
|
19945
|
+
* The escape sequence used for message param values.
|
|
19946
|
+
*/
|
|
19947
|
+
const ESCAPE = '\uFFFD';
|
|
19773
19948
|
/**
|
|
19774
19949
|
* Lifts i18n properties into the consts array.
|
|
19775
19950
|
* TODO: Can we use `ConstCollectedExpr`?
|
|
19951
|
+
* TODO: The way the various attributes are linked together is very complex. Perhaps we could
|
|
19952
|
+
* simplify the process, maybe by combining the context and message ops?
|
|
19776
19953
|
*/
|
|
19777
19954
|
function collectI18nConsts(job) {
|
|
19778
19955
|
const fileBasedI18nSuffix = job.relativeContextFilePath.replace(/[^A-Za-z0-9]/g, '_').toUpperCase() + '_';
|
|
19779
|
-
|
|
19780
|
-
//
|
|
19956
|
+
// Step One: Build up various lookup maps we need to collect all the consts.
|
|
19957
|
+
// Context Xref -> Extracted Attribute Op
|
|
19958
|
+
const extractedAttributesByI18nContext = new Map();
|
|
19959
|
+
// Element/ElementStart Xref -> I18n Attributes config op
|
|
19960
|
+
const i18nAttributesByElement = new Map();
|
|
19961
|
+
// Element/ElementStart Xref -> All I18n Expression ops for attrs on that target
|
|
19962
|
+
const i18nExpressionsByElement = new Map();
|
|
19963
|
+
// I18n Message Xref -> I18n Message Op (TODO: use a central op map)
|
|
19781
19964
|
const messages = new Map();
|
|
19965
|
+
for (const unit of job.units) {
|
|
19966
|
+
for (const op of unit.ops()) {
|
|
19967
|
+
if (op.kind === OpKind.ExtractedAttribute && op.i18nContext !== null) {
|
|
19968
|
+
extractedAttributesByI18nContext.set(op.i18nContext, op);
|
|
19969
|
+
}
|
|
19970
|
+
else if (op.kind === OpKind.I18nAttributes) {
|
|
19971
|
+
i18nAttributesByElement.set(op.target, op);
|
|
19972
|
+
}
|
|
19973
|
+
else if (op.kind === OpKind.I18nExpression && op.usage === I18nExpressionFor.I18nAttribute) {
|
|
19974
|
+
const expressions = i18nExpressionsByElement.get(op.target) ?? [];
|
|
19975
|
+
expressions.push(op);
|
|
19976
|
+
i18nExpressionsByElement.set(op.target, expressions);
|
|
19977
|
+
}
|
|
19978
|
+
else if (op.kind === OpKind.I18nMessage) {
|
|
19979
|
+
messages.set(op.xref, op);
|
|
19980
|
+
}
|
|
19981
|
+
}
|
|
19982
|
+
}
|
|
19983
|
+
// Step Two: Serialize the extracted i18n messages for root i18n blocks and i18n attributes into
|
|
19984
|
+
// the const array.
|
|
19985
|
+
//
|
|
19986
|
+
// Also, each i18n message will have a variable expression that can refer to its
|
|
19987
|
+
// value. Store these expressions in the appropriate place:
|
|
19988
|
+
// 1. For normal i18n content, it also goes in the const array. We save the const index to use
|
|
19989
|
+
// later.
|
|
19990
|
+
// 2. For extracted attributes, it becomes the value of the extracted attribute instruction.
|
|
19991
|
+
// 3. For i18n bindings, it will go in a separate const array instruction below; for now, we just
|
|
19992
|
+
// save it.
|
|
19993
|
+
const i18nValuesByContext = new Map();
|
|
19994
|
+
const messageConstIndices = new Map();
|
|
19782
19995
|
for (const unit of job.units) {
|
|
19783
19996
|
for (const op of unit.create) {
|
|
19784
19997
|
if (op.kind === OpKind.I18nMessage) {
|
|
19785
|
-
|
|
19998
|
+
if (op.messagePlaceholder === null) {
|
|
19999
|
+
const { mainVar, statements } = collectMessage(job, fileBasedI18nSuffix, messages, op);
|
|
20000
|
+
if (op.i18nBlock !== null) {
|
|
20001
|
+
// This is a regular i18n message with a corresponding i18n block. Collect it into the
|
|
20002
|
+
// const array.
|
|
20003
|
+
const i18nConst = job.addConst(mainVar, statements);
|
|
20004
|
+
messageConstIndices.set(op.i18nBlock, i18nConst);
|
|
20005
|
+
}
|
|
20006
|
+
else {
|
|
20007
|
+
// This is an i18n attribute. Extract the initializers into the const pool.
|
|
20008
|
+
job.constsInitializers.push(...statements);
|
|
20009
|
+
// Save the i18n variable value for later.
|
|
20010
|
+
i18nValuesByContext.set(op.i18nContext, mainVar);
|
|
20011
|
+
// This i18n message may correspond to an individual extracted attribute. If so, The
|
|
20012
|
+
// value of that attribute is updated to read the extracted i18n variable.
|
|
20013
|
+
const attributeForMessage = extractedAttributesByI18nContext.get(op.i18nContext);
|
|
20014
|
+
if (attributeForMessage !== undefined) {
|
|
20015
|
+
attributeForMessage.expression = mainVar;
|
|
20016
|
+
}
|
|
20017
|
+
}
|
|
20018
|
+
}
|
|
19786
20019
|
OpList.remove(op);
|
|
19787
20020
|
}
|
|
19788
20021
|
}
|
|
19789
20022
|
}
|
|
19790
|
-
//
|
|
19791
|
-
|
|
19792
|
-
|
|
19793
|
-
|
|
19794
|
-
|
|
20023
|
+
// Step Three: Serialize I18nAttributes configurations into the const array. Each I18nAttributes
|
|
20024
|
+
// instruction has a config array, which contains k-v pairs describing each binding name, and the
|
|
20025
|
+
// i18n variable that provides the value.
|
|
20026
|
+
for (const unit of job.units) {
|
|
20027
|
+
for (const elem of unit.create) {
|
|
20028
|
+
if (isElementOrContainerOp(elem)) {
|
|
20029
|
+
const i18nAttributes = i18nAttributesByElement.get(elem.xref);
|
|
20030
|
+
if (i18nAttributes === undefined) {
|
|
20031
|
+
// This element is not associated with an i18n attributes configuration instruction.
|
|
20032
|
+
continue;
|
|
20033
|
+
}
|
|
20034
|
+
let i18nExpressions = i18nExpressionsByElement.get(elem.xref);
|
|
20035
|
+
if (i18nExpressions === undefined) {
|
|
20036
|
+
// Unused i18nAttributes should have already been removed.
|
|
20037
|
+
// TODO: Should the removal of those dead instructions be merged with this phase?
|
|
20038
|
+
throw new Error('AssertionError: Could not find any i18n expressions associated with an I18nAttributes instruction');
|
|
20039
|
+
}
|
|
20040
|
+
// Find expressions for all the unique property names, removing duplicates.
|
|
20041
|
+
const seenPropertyNames = new Set();
|
|
20042
|
+
i18nExpressions = i18nExpressions.filter(i18nExpr => {
|
|
20043
|
+
const seen = (seenPropertyNames.has(i18nExpr.name));
|
|
20044
|
+
seenPropertyNames.add(i18nExpr.name);
|
|
20045
|
+
return !seen;
|
|
20046
|
+
});
|
|
20047
|
+
const i18nAttributeConfig = i18nExpressions.flatMap(i18nExpr => {
|
|
20048
|
+
const i18nExprValue = i18nValuesByContext.get(i18nExpr.context);
|
|
20049
|
+
if (i18nExprValue === undefined) {
|
|
20050
|
+
throw new Error('AssertionError: Could not find i18n expression\'s value');
|
|
20051
|
+
}
|
|
20052
|
+
return [literal(i18nExpr.name), i18nExprValue];
|
|
20053
|
+
});
|
|
20054
|
+
i18nAttributes.i18nAttributesConfig =
|
|
20055
|
+
job.addConst(new LiteralArrayExpr(i18nAttributeConfig));
|
|
20056
|
+
}
|
|
19795
20057
|
}
|
|
19796
20058
|
}
|
|
19797
|
-
//
|
|
20059
|
+
// Step Four: Propagate the extracted const index into i18n ops that messages were extracted from.
|
|
19798
20060
|
for (const unit of job.units) {
|
|
19799
20061
|
for (const op of unit.create) {
|
|
19800
20062
|
if (op.kind === OpKind.I18nStart) {
|
|
19801
|
-
|
|
20063
|
+
const msgIndex = messageConstIndices.get(op.root);
|
|
20064
|
+
if (msgIndex === undefined) {
|
|
20065
|
+
throw new Error('AssertionError: Could not find corresponding i18n block index for an i18n message op; was an i18n message incorrectly assumed to correspond to an attribute?');
|
|
20066
|
+
}
|
|
20067
|
+
op.messageIndex = msgIndex;
|
|
19802
20068
|
}
|
|
19803
20069
|
}
|
|
19804
20070
|
}
|
|
@@ -19808,18 +20074,23 @@ function collectI18nConsts(job) {
|
|
|
19808
20074
|
* This will recursively collect any sub-messages referenced from the parent message as well.
|
|
19809
20075
|
*/
|
|
19810
20076
|
function collectMessage(job, fileBasedI18nSuffix, messages, messageOp) {
|
|
19811
|
-
// Recursively collect any sub-messages,
|
|
20077
|
+
// Recursively collect any sub-messages, record each sub-message's main variable under its
|
|
20078
|
+
// placeholder so that we can add them to the params for the parent message. It is possible
|
|
20079
|
+
// that multiple sub-messages will share the same placeholder, so we need to track an array of
|
|
20080
|
+
// variables for each placeholder.
|
|
19812
20081
|
const statements = [];
|
|
20082
|
+
const subMessagePlaceholders = new Map();
|
|
19813
20083
|
for (const subMessageId of messageOp.subMessages) {
|
|
19814
20084
|
const subMessage = messages.get(subMessageId);
|
|
19815
20085
|
const { mainVar: subMessageVar, statements: subMessageStatements } = collectMessage(job, fileBasedI18nSuffix, messages, subMessage);
|
|
19816
20086
|
statements.push(...subMessageStatements);
|
|
19817
|
-
|
|
20087
|
+
const subMessages = subMessagePlaceholders.get(subMessage.messagePlaceholder) ?? [];
|
|
20088
|
+
subMessages.push(subMessageVar);
|
|
20089
|
+
subMessagePlaceholders.set(subMessage.messagePlaceholder, subMessages);
|
|
19818
20090
|
}
|
|
20091
|
+
addSubMessageParams(messageOp, subMessagePlaceholders);
|
|
19819
20092
|
// Sort the params for consistency with TemaplateDefinitionBuilder output.
|
|
19820
20093
|
messageOp.params = new Map([...messageOp.params.entries()].sort());
|
|
19821
|
-
// Check that the message has all of its parameters filled out.
|
|
19822
|
-
assertAllParamsResolved(messageOp);
|
|
19823
20094
|
const mainVar = variable(job.pool.uniqueName(TRANSLATION_VAR_PREFIX));
|
|
19824
20095
|
// Closure Compiler requires const names to start with `MSG_` but disallows any other
|
|
19825
20096
|
// const to start with `MSG_`. We define a variable starting with `MSG_` just for the
|
|
@@ -19830,10 +20101,11 @@ function collectMessage(job, fileBasedI18nSuffix, messages, messageOp) {
|
|
|
19830
20101
|
// set in post-processing.
|
|
19831
20102
|
if (messageOp.needsPostprocessing) {
|
|
19832
20103
|
// Sort the post-processing params for consistency with TemaplateDefinitionBuilder output.
|
|
19833
|
-
|
|
20104
|
+
const postprocessingParams = Object.fromEntries([...messageOp.postprocessingParams.entries()].sort());
|
|
20105
|
+
const formattedPostprocessingParams = formatI18nPlaceholderNamesInMap(postprocessingParams, /* useCamelCase */ false);
|
|
19834
20106
|
const extraTransformFnParams = [];
|
|
19835
20107
|
if (messageOp.postprocessingParams.size > 0) {
|
|
19836
|
-
extraTransformFnParams.push(
|
|
20108
|
+
extraTransformFnParams.push(mapLiteral(formattedPostprocessingParams, /* quoted */ true));
|
|
19837
20109
|
}
|
|
19838
20110
|
transformFn = (expr) => importExpr(Identifiers.i18nPostprocess).callFn([expr, ...extraTransformFnParams]);
|
|
19839
20111
|
}
|
|
@@ -19841,6 +20113,26 @@ function collectMessage(job, fileBasedI18nSuffix, messages, messageOp) {
|
|
|
19841
20113
|
statements.push(...getTranslationDeclStmts$1(messageOp.message, mainVar, closureVar, messageOp.params, transformFn));
|
|
19842
20114
|
return { mainVar, statements };
|
|
19843
20115
|
}
|
|
20116
|
+
/**
|
|
20117
|
+
* Adds the given subMessage placeholders to the given message op.
|
|
20118
|
+
*
|
|
20119
|
+
* If a placeholder only corresponds to a single sub-message variable, we just set that variable
|
|
20120
|
+
* as the param value. However, if the placeholder corresponds to multiple sub-message
|
|
20121
|
+
* variables, we need to add a special placeholder value that is handled by the post-processing
|
|
20122
|
+
* step. We then add the array of variables as a post-processing param.
|
|
20123
|
+
*/
|
|
20124
|
+
function addSubMessageParams(messageOp, subMessagePlaceholders) {
|
|
20125
|
+
for (const [placeholder, subMessages] of subMessagePlaceholders) {
|
|
20126
|
+
if (subMessages.length === 1) {
|
|
20127
|
+
messageOp.params.set(placeholder, subMessages[0]);
|
|
20128
|
+
}
|
|
20129
|
+
else {
|
|
20130
|
+
messageOp.params.set(placeholder, literal(`${ESCAPE}${I18N_ICU_MAPPING_PREFIX}${placeholder}${ESCAPE}`));
|
|
20131
|
+
messageOp.postprocessingParams.set(placeholder, literalArr(subMessages));
|
|
20132
|
+
messageOp.needsPostprocessing = true;
|
|
20133
|
+
}
|
|
20134
|
+
}
|
|
20135
|
+
}
|
|
19844
20136
|
/**
|
|
19845
20137
|
* Generate statements that define a given translation message.
|
|
19846
20138
|
*
|
|
@@ -19863,7 +20155,8 @@ function collectMessage(job, fileBasedI18nSuffix, messages, messageOp) {
|
|
|
19863
20155
|
* @param closureVar The variable for Closure `goog.getMsg` calls, e.g. `MSG_EXTERNAL_XXX`.
|
|
19864
20156
|
* @param params Object mapping placeholder names to their values (e.g.
|
|
19865
20157
|
* `{ "interpolation": "\uFFFD0\uFFFD" }`).
|
|
19866
|
-
* @param transformFn Optional transformation function that will be applied to the translation
|
|
20158
|
+
* @param transformFn Optional transformation function that will be applied to the translation
|
|
20159
|
+
* (e.g.
|
|
19867
20160
|
* post-processing).
|
|
19868
20161
|
* @returns An array of statements that defined a given translation.
|
|
19869
20162
|
*/
|
|
@@ -19908,28 +20201,13 @@ function i18nGenerateClosureVar(pool, messageId, fileBasedI18nSuffix, useExterna
|
|
|
19908
20201
|
}
|
|
19909
20202
|
return variable(name);
|
|
19910
20203
|
}
|
|
19911
|
-
/**
|
|
19912
|
-
* Asserts that all of the message's placeholders have values.
|
|
19913
|
-
*/
|
|
19914
|
-
function assertAllParamsResolved(op) {
|
|
19915
|
-
for (let placeholder in op.message.placeholders) {
|
|
19916
|
-
placeholder = placeholder.trimEnd();
|
|
19917
|
-
if (!op.params.has(placeholder) && !op.postprocessingParams.has(placeholder)) {
|
|
19918
|
-
throw Error(`Failed to resolve i18n placeholder: ${placeholder}`);
|
|
19919
|
-
}
|
|
19920
|
-
}
|
|
19921
|
-
for (let placeholder in op.message.placeholderToMessage) {
|
|
19922
|
-
placeholder = placeholder.trimEnd();
|
|
19923
|
-
if (!op.params.has(placeholder) && !op.postprocessingParams.has(placeholder)) {
|
|
19924
|
-
throw Error(`Failed to resolve i18n message placeholder: ${placeholder}`);
|
|
19925
|
-
}
|
|
19926
|
-
}
|
|
19927
|
-
}
|
|
19928
20204
|
|
|
19929
20205
|
/**
|
|
19930
20206
|
* Removes text nodes within i18n blocks since they are already hardcoded into the i18n message.
|
|
20207
|
+
* Also, replaces interpolations on these text nodes with i18n expressions of the non-text portions,
|
|
20208
|
+
* which will be applied later.
|
|
19931
20209
|
*/
|
|
19932
|
-
function
|
|
20210
|
+
function convertI18nText(job) {
|
|
19933
20211
|
for (const unit of job.units) {
|
|
19934
20212
|
// Remove all text nodes within i18n blocks, their content is already captured in the i18n
|
|
19935
20213
|
// message.
|
|
@@ -19984,7 +20262,7 @@ function extractI18nText(job) {
|
|
|
19984
20262
|
const expr = op.interpolation.expressions[i];
|
|
19985
20263
|
// For now, this i18nExpression depends on the slot context of the enclosing i18n block.
|
|
19986
20264
|
// Later, we will modify this, and advance to a different point.
|
|
19987
|
-
ops.push(createI18nExpressionOp(contextId, i18nOp.xref, i18nOp.handle, expr, op.i18nPlaceholders[i], resolutionTime, expr.sourceSpan ?? op.sourceSpan));
|
|
20265
|
+
ops.push(createI18nExpressionOp(contextId, i18nOp.xref, i18nOp.xref, i18nOp.handle, expr, op.interpolation.i18nPlaceholders[i], resolutionTime, I18nExpressionFor.I18nText, '', expr.sourceSpan ?? op.sourceSpan));
|
|
19988
20266
|
}
|
|
19989
20267
|
OpList.replaceWithMany(op, ops);
|
|
19990
20268
|
break;
|
|
@@ -20522,14 +20800,14 @@ function parseExtractedStyles(job) {
|
|
|
20522
20800
|
if (op.name === 'style') {
|
|
20523
20801
|
const parsedStyles = parse(op.expression.value);
|
|
20524
20802
|
for (let i = 0; i < parsedStyles.length - 1; i += 2) {
|
|
20525
|
-
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.StyleProperty, parsedStyles[i], literal(parsedStyles[i + 1])), op);
|
|
20803
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.StyleProperty, parsedStyles[i], literal(parsedStyles[i + 1]), null), op);
|
|
20526
20804
|
}
|
|
20527
20805
|
OpList.remove(op);
|
|
20528
20806
|
}
|
|
20529
20807
|
else if (op.name === 'class') {
|
|
20530
20808
|
const parsedClasses = op.expression.value.trim().split(/\s+/g);
|
|
20531
20809
|
for (const parsedClass of parsedClasses) {
|
|
20532
|
-
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.ClassName, parsedClass, null), op);
|
|
20810
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.ClassName, parsedClass, null, null), op);
|
|
20533
20811
|
}
|
|
20534
20812
|
OpList.remove(op);
|
|
20535
20813
|
}
|
|
@@ -20545,18 +20823,30 @@ function parseExtractedStyles(job) {
|
|
|
20545
20823
|
function removeContentSelectors(job) {
|
|
20546
20824
|
for (const unit of job.units) {
|
|
20547
20825
|
const elements = createOpXrefMap(unit);
|
|
20548
|
-
for (const op of unit.
|
|
20826
|
+
for (const op of unit.ops()) {
|
|
20549
20827
|
switch (op.kind) {
|
|
20550
20828
|
case OpKind.Binding:
|
|
20551
20829
|
const target = lookupInXrefMap(elements, op.target);
|
|
20552
|
-
if (op.name
|
|
20830
|
+
if (isSelectAttribute(op.name) && target.kind === OpKind.Projection) {
|
|
20553
20831
|
OpList.remove(op);
|
|
20554
20832
|
}
|
|
20555
20833
|
break;
|
|
20834
|
+
case OpKind.Projection:
|
|
20835
|
+
// op.attributes is an array of [attr1-name, attr1-value, attr2-name, attr2-value, ...],
|
|
20836
|
+
// find the "select" attribute and remove its name and corresponding value.
|
|
20837
|
+
for (let i = op.attributes.length - 2; i >= 0; i -= 2) {
|
|
20838
|
+
if (isSelectAttribute(op.attributes[i])) {
|
|
20839
|
+
op.attributes.splice(i, 2);
|
|
20840
|
+
}
|
|
20841
|
+
}
|
|
20842
|
+
break;
|
|
20556
20843
|
}
|
|
20557
20844
|
}
|
|
20558
20845
|
}
|
|
20559
20846
|
}
|
|
20847
|
+
function isSelectAttribute(name) {
|
|
20848
|
+
return name.toLowerCase() === 'select';
|
|
20849
|
+
}
|
|
20560
20850
|
/**
|
|
20561
20851
|
* Looks up an element in the given map by xref ID.
|
|
20562
20852
|
*/
|
|
@@ -20676,6 +20966,10 @@ function propagateI18nBlocksToTemplates(unit, subTemplateIndex) {
|
|
|
20676
20966
|
i18nBlock = op;
|
|
20677
20967
|
break;
|
|
20678
20968
|
case OpKind.I18nEnd:
|
|
20969
|
+
// When we exit a root-level i18n block, reset the sub-template index counter.
|
|
20970
|
+
if (i18nBlock.subTemplateIndex === null) {
|
|
20971
|
+
subTemplateIndex = 0;
|
|
20972
|
+
}
|
|
20679
20973
|
i18nBlock = null;
|
|
20680
20974
|
break;
|
|
20681
20975
|
case OpKind.Template:
|
|
@@ -21017,6 +21311,10 @@ function i18n(slot, constIndex, subTemplateIndex) {
|
|
|
21017
21311
|
function i18nEnd() {
|
|
21018
21312
|
return call(Identifiers.i18nEnd, [], null);
|
|
21019
21313
|
}
|
|
21314
|
+
function i18nAttributes(slot, i18nAttributesConfig) {
|
|
21315
|
+
const args = [literal(slot), literal(i18nAttributesConfig)];
|
|
21316
|
+
return call(Identifiers.i18nAttributes, args, null);
|
|
21317
|
+
}
|
|
21020
21318
|
function property(name, expression, sanitizer, sourceSpan) {
|
|
21021
21319
|
const args = [literal(name), expression];
|
|
21022
21320
|
if (sanitizer !== null) {
|
|
@@ -21403,6 +21701,12 @@ function reifyCreateOperations(unit, ops) {
|
|
|
21403
21701
|
case OpKind.I18n:
|
|
21404
21702
|
OpList.replace(op, i18n(op.handle.slot, op.messageIndex, op.subTemplateIndex));
|
|
21405
21703
|
break;
|
|
21704
|
+
case OpKind.I18nAttributes:
|
|
21705
|
+
if (op.i18nAttributesConfig === null) {
|
|
21706
|
+
throw new Error(`AssertionError: i18nAttributesConfig was not set`);
|
|
21707
|
+
}
|
|
21708
|
+
OpList.replace(op, i18nAttributes(op.handle.slot, op.i18nAttributesConfig));
|
|
21709
|
+
break;
|
|
21406
21710
|
case OpKind.Template:
|
|
21407
21711
|
if (!(unit instanceof ViewCompilationUnit)) {
|
|
21408
21712
|
throw new Error(`AssertionError: must be compiling a component`);
|
|
@@ -21744,6 +22048,31 @@ function removeI18nContexts(job) {
|
|
|
21744
22048
|
}
|
|
21745
22049
|
}
|
|
21746
22050
|
|
|
22051
|
+
/**
|
|
22052
|
+
* i18nAttributes ops will be generated for each i18n attribute. However, not all i18n attribues
|
|
22053
|
+
* will contain dynamic content, and so some of these i18nAttributes ops may be unnecessary.
|
|
22054
|
+
*/
|
|
22055
|
+
function removeUnusedI18nAttributesOps(job) {
|
|
22056
|
+
for (const unit of job.units) {
|
|
22057
|
+
const ownersWithI18nExpressions = new Set();
|
|
22058
|
+
for (const op of unit.update) {
|
|
22059
|
+
switch (op.kind) {
|
|
22060
|
+
case OpKind.I18nExpression:
|
|
22061
|
+
ownersWithI18nExpressions.add(op.i18nOwner);
|
|
22062
|
+
}
|
|
22063
|
+
}
|
|
22064
|
+
for (const op of unit.create) {
|
|
22065
|
+
switch (op.kind) {
|
|
22066
|
+
case OpKind.I18nAttributes:
|
|
22067
|
+
if (ownersWithI18nExpressions.has(op.xref)) {
|
|
22068
|
+
continue;
|
|
22069
|
+
}
|
|
22070
|
+
OpList.remove(op);
|
|
22071
|
+
}
|
|
22072
|
+
}
|
|
22073
|
+
}
|
|
22074
|
+
}
|
|
22075
|
+
|
|
21747
22076
|
/**
|
|
21748
22077
|
* Inside the body of a repeater, certain context variables (such as `$first`) are ambiently
|
|
21749
22078
|
* available. This phase finds those variable usages, and replaces them with the appropriate
|
|
@@ -21875,10 +22204,14 @@ function resolveI18nElementPlaceholders(job) {
|
|
|
21875
22204
|
}
|
|
21876
22205
|
resolvePlaceholdersForView(job, job.root, i18nContexts, elements);
|
|
21877
22206
|
}
|
|
21878
|
-
|
|
22207
|
+
/**
|
|
22208
|
+
* Recursively resolves element and template tag placeholders in the given view.
|
|
22209
|
+
*/
|
|
22210
|
+
function resolvePlaceholdersForView(job, unit, i18nContexts, elements, pendingStructuralDirective) {
|
|
21879
22211
|
// Track the current i18n op and corresponding i18n context op as we step through the creation
|
|
21880
22212
|
// IR.
|
|
21881
22213
|
let currentOps = null;
|
|
22214
|
+
let pendingStructuralDirectiveCloses = new Map();
|
|
21882
22215
|
for (const op of unit.create) {
|
|
21883
22216
|
switch (op.kind) {
|
|
21884
22217
|
case OpKind.I18nStart:
|
|
@@ -21897,14 +22230,14 @@ function resolvePlaceholdersForView(job, unit, i18nContexts, elements) {
|
|
|
21897
22230
|
if (currentOps === null) {
|
|
21898
22231
|
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
21899
22232
|
}
|
|
21900
|
-
|
|
21901
|
-
|
|
21902
|
-
//
|
|
21903
|
-
|
|
21904
|
-
|
|
21905
|
-
flags |= I18nParamValueFlags.CloseTag;
|
|
22233
|
+
recordElementStart(op, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22234
|
+
// If there is a separate close tag placeholder for this element, save the pending
|
|
22235
|
+
// structural directive so we can pass it to the closing tag as well.
|
|
22236
|
+
if (pendingStructuralDirective && op.i18nPlaceholder.closeName) {
|
|
22237
|
+
pendingStructuralDirectiveCloses.set(op.xref, pendingStructuralDirective);
|
|
21906
22238
|
}
|
|
21907
|
-
|
|
22239
|
+
// Clear out the pending structural directive now that its been accounted for.
|
|
22240
|
+
pendingStructuralDirective = undefined;
|
|
21908
22241
|
}
|
|
21909
22242
|
break;
|
|
21910
22243
|
case OpKind.ElementEnd:
|
|
@@ -21913,42 +22246,134 @@ function resolvePlaceholdersForView(job, unit, i18nContexts, elements) {
|
|
|
21913
22246
|
const startOp = elements.get(op.xref);
|
|
21914
22247
|
if (startOp && startOp.i18nPlaceholder !== undefined) {
|
|
21915
22248
|
if (currentOps === null) {
|
|
21916
|
-
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
21917
|
-
}
|
|
21918
|
-
const { closeName } = startOp.i18nPlaceholder;
|
|
21919
|
-
// Self-closing tags don't have a closing tag placeholder.
|
|
21920
|
-
if (closeName !== '') {
|
|
21921
|
-
addParam(currentOps.i18nContext.params, closeName, startOp.handle.slot, currentOps.i18nBlock.subTemplateIndex, I18nParamValueFlags.ElementTag | I18nParamValueFlags.CloseTag);
|
|
22249
|
+
throw Error('AssertionError: i18n tag placeholder should only occur inside an i18n block');
|
|
21922
22250
|
}
|
|
22251
|
+
recordElementClose(startOp, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirectiveCloses.get(op.xref));
|
|
22252
|
+
// Clear out the pending structural directive close that was accounted for.
|
|
22253
|
+
pendingStructuralDirectiveCloses.delete(op.xref);
|
|
21923
22254
|
}
|
|
21924
22255
|
break;
|
|
21925
|
-
case OpKind.
|
|
21926
|
-
// For
|
|
21927
|
-
// corresponding
|
|
22256
|
+
case OpKind.Projection:
|
|
22257
|
+
// For content projections with i18n placeholders, record its slot value in the params map
|
|
22258
|
+
// under the corresponding tag start and close placeholders.
|
|
21928
22259
|
if (op.i18nPlaceholder !== undefined) {
|
|
21929
22260
|
if (currentOps === null) {
|
|
21930
22261
|
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
21931
22262
|
}
|
|
21932
|
-
|
|
21933
|
-
|
|
21934
|
-
|
|
21935
|
-
|
|
21936
|
-
|
|
21937
|
-
|
|
21938
|
-
|
|
21939
|
-
|
|
22263
|
+
recordElementStart(op, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22264
|
+
recordElementClose(op, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22265
|
+
// Clear out the pending structural directive now that its been accounted for.
|
|
22266
|
+
pendingStructuralDirective = undefined;
|
|
22267
|
+
}
|
|
22268
|
+
break;
|
|
22269
|
+
case OpKind.Template:
|
|
22270
|
+
if (op.i18nPlaceholder === undefined) {
|
|
22271
|
+
// If there is no i18n placeholder, just recurse into the view in case it contains i18n
|
|
22272
|
+
// blocks.
|
|
21940
22273
|
resolvePlaceholdersForView(job, job.views.get(op.xref), i18nContexts, elements);
|
|
21941
|
-
if (!isSelfClosing) {
|
|
21942
|
-
addParam(currentOps.i18nContext.params, closeName, op.handle.slot, subTemplateIndex, I18nParamValueFlags.TemplateTag | I18nParamValueFlags.CloseTag);
|
|
21943
|
-
}
|
|
21944
22274
|
}
|
|
21945
22275
|
else {
|
|
21946
|
-
|
|
22276
|
+
if (currentOps === null) {
|
|
22277
|
+
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
22278
|
+
}
|
|
22279
|
+
if (op.templateKind === TemplateKind.Structural) {
|
|
22280
|
+
// If this is a structural directive template, don't record anything yet. Instead pass
|
|
22281
|
+
// the current template as a pending structural directive to be recorded when we find
|
|
22282
|
+
// the element, content, or template it belongs to. This allows us to create combined
|
|
22283
|
+
// values that represent, e.g. the start of a template and element at the same time.
|
|
22284
|
+
resolvePlaceholdersForView(job, job.views.get(op.xref), i18nContexts, elements, op);
|
|
22285
|
+
}
|
|
22286
|
+
else {
|
|
22287
|
+
// If this is some other kind of template, we can record its start, recurse into its
|
|
22288
|
+
// view, and then record its end.
|
|
22289
|
+
recordTemplateStart(job, op, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22290
|
+
resolvePlaceholdersForView(job, job.views.get(op.xref), i18nContexts, elements);
|
|
22291
|
+
recordTemplateClose(job, op, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22292
|
+
pendingStructuralDirective = undefined;
|
|
22293
|
+
}
|
|
21947
22294
|
}
|
|
21948
22295
|
break;
|
|
21949
22296
|
}
|
|
21950
22297
|
}
|
|
21951
22298
|
}
|
|
22299
|
+
/**
|
|
22300
|
+
* Records an i18n param value for the start of an element.
|
|
22301
|
+
*/
|
|
22302
|
+
function recordElementStart(op, i18nContext, i18nBlock, structuralDirective) {
|
|
22303
|
+
const { startName, closeName } = op.i18nPlaceholder;
|
|
22304
|
+
let flags = I18nParamValueFlags.ElementTag | I18nParamValueFlags.OpenTag;
|
|
22305
|
+
let value = op.handle.slot;
|
|
22306
|
+
// If the element is associated with a structural directive, start it as well.
|
|
22307
|
+
if (structuralDirective !== undefined) {
|
|
22308
|
+
flags |= I18nParamValueFlags.TemplateTag;
|
|
22309
|
+
value = { element: value, template: structuralDirective.handle.slot };
|
|
22310
|
+
}
|
|
22311
|
+
// For self-closing tags, there is no close tag placeholder. Instead, the start tag
|
|
22312
|
+
// placeholder accounts for the start and close of the element.
|
|
22313
|
+
if (!closeName) {
|
|
22314
|
+
flags |= I18nParamValueFlags.CloseTag;
|
|
22315
|
+
}
|
|
22316
|
+
addParam(i18nContext.params, startName, value, i18nBlock.subTemplateIndex, flags);
|
|
22317
|
+
}
|
|
22318
|
+
/**
|
|
22319
|
+
* Records an i18n param value for the closing of an element.
|
|
22320
|
+
*/
|
|
22321
|
+
function recordElementClose(op, i18nContext, i18nBlock, structuralDirective) {
|
|
22322
|
+
const { closeName } = op.i18nPlaceholder;
|
|
22323
|
+
// Self-closing tags don't have a closing tag placeholder, instead the element closing is
|
|
22324
|
+
// recorded via an additional flag on the element start value.
|
|
22325
|
+
if (closeName) {
|
|
22326
|
+
let flags = I18nParamValueFlags.ElementTag | I18nParamValueFlags.CloseTag;
|
|
22327
|
+
let value = op.handle.slot;
|
|
22328
|
+
// If the element is associated with a structural directive, close it as well.
|
|
22329
|
+
if (structuralDirective !== undefined) {
|
|
22330
|
+
flags |= I18nParamValueFlags.TemplateTag;
|
|
22331
|
+
value = { element: value, template: structuralDirective.handle.slot };
|
|
22332
|
+
}
|
|
22333
|
+
addParam(i18nContext.params, closeName, value, i18nBlock.subTemplateIndex, flags);
|
|
22334
|
+
}
|
|
22335
|
+
}
|
|
22336
|
+
/**
|
|
22337
|
+
* Records an i18n param value for the start of a template.
|
|
22338
|
+
*/
|
|
22339
|
+
function recordTemplateStart(job, op, i18nContext, i18nBlock, structuralDirective) {
|
|
22340
|
+
let { startName, closeName } = op.i18nPlaceholder;
|
|
22341
|
+
let flags = I18nParamValueFlags.TemplateTag | I18nParamValueFlags.OpenTag;
|
|
22342
|
+
// For self-closing tags, there is no close tag placeholder. Instead, the start tag
|
|
22343
|
+
// placeholder accounts for the start and close of the element.
|
|
22344
|
+
if (!closeName) {
|
|
22345
|
+
flags |= I18nParamValueFlags.CloseTag;
|
|
22346
|
+
}
|
|
22347
|
+
// If the template is associated with a structural directive, record the structural directive's
|
|
22348
|
+
// start first. Since this template must be in the structural directive's view, we can just
|
|
22349
|
+
// directly use the current i18n block's sub-template index.
|
|
22350
|
+
if (structuralDirective !== undefined) {
|
|
22351
|
+
addParam(i18nContext.params, startName, structuralDirective.handle.slot, i18nBlock.subTemplateIndex, flags);
|
|
22352
|
+
}
|
|
22353
|
+
// Record the start of the template. For the sub-template index, pass the index for the template's
|
|
22354
|
+
// view, rather than the current i18n block's index.
|
|
22355
|
+
addParam(i18nContext.params, startName, op.handle.slot, getSubTemplateIndexForTemplateTag(job, i18nBlock, op), flags);
|
|
22356
|
+
}
|
|
22357
|
+
/**
|
|
22358
|
+
* Records an i18n param value for the closing of a template.
|
|
22359
|
+
*/
|
|
22360
|
+
function recordTemplateClose(job, op, i18nContext, i18nBlock, structuralDirective) {
|
|
22361
|
+
const { startName, closeName } = op.i18nPlaceholder;
|
|
22362
|
+
const flags = I18nParamValueFlags.TemplateTag | I18nParamValueFlags.CloseTag;
|
|
22363
|
+
// Self-closing tags don't have a closing tag placeholder, instead the template's closing is
|
|
22364
|
+
// recorded via an additional flag on the template start value.
|
|
22365
|
+
if (closeName) {
|
|
22366
|
+
// Record the closing of the template. For the sub-template index, pass the index for the
|
|
22367
|
+
// template's view, rather than the current i18n block's index.
|
|
22368
|
+
addParam(i18nContext.params, closeName, op.handle.slot, getSubTemplateIndexForTemplateTag(job, i18nBlock, op), flags);
|
|
22369
|
+
// If the template is associated with a structural directive, record the structural directive's
|
|
22370
|
+
// closing after. Since this template must be in the structural directive's view, we can just
|
|
22371
|
+
// directly use the current i18n block's sub-template index.
|
|
22372
|
+
if (structuralDirective !== undefined) {
|
|
22373
|
+
addParam(i18nContext.params, closeName, structuralDirective.handle.slot, i18nBlock.subTemplateIndex, flags);
|
|
22374
|
+
}
|
|
22375
|
+
}
|
|
22376
|
+
}
|
|
21952
22377
|
/**
|
|
21953
22378
|
* Get the subTemplateIndex for the given template op. For template ops, use the subTemplateIndex of
|
|
21954
22379
|
* the child i18n block inside the template.
|
|
@@ -21961,7 +22386,9 @@ function getSubTemplateIndexForTemplateTag(job, i18nOp, op) {
|
|
|
21961
22386
|
}
|
|
21962
22387
|
return i18nOp.subTemplateIndex;
|
|
21963
22388
|
}
|
|
21964
|
-
/**
|
|
22389
|
+
/**
|
|
22390
|
+
* Add a param value to the given params map.
|
|
22391
|
+
*/
|
|
21965
22392
|
function addParam(params, placeholder, value, subTemplateIndex, flags) {
|
|
21966
22393
|
const values = params.get(placeholder) ?? [];
|
|
21967
22394
|
values.push({ value, subTemplateIndex, flags });
|
|
@@ -21987,14 +22414,19 @@ function resolveI18nExpressionPlaceholders(job) {
|
|
|
21987
22414
|
}
|
|
21988
22415
|
}
|
|
21989
22416
|
}
|
|
21990
|
-
// Keep track of the next available expression index
|
|
22417
|
+
// Keep track of the next available expression index for each i18n message.
|
|
21991
22418
|
const expressionIndices = new Map();
|
|
22419
|
+
// Keep track of a reference index for each expression.
|
|
22420
|
+
// We use different references for normal i18n expressio and attribute i18n expressions. This is
|
|
22421
|
+
// because child i18n blocks in templates don't get their own context, since they're rolled into
|
|
22422
|
+
// the translated message of the parent, but they may target a different slot.
|
|
22423
|
+
const referenceIndex = (op) => op.usage === I18nExpressionFor.I18nText ? op.i18nOwner : op.context;
|
|
21992
22424
|
for (const unit of job.units) {
|
|
21993
22425
|
for (const op of unit.update) {
|
|
21994
22426
|
if (op.kind === OpKind.I18nExpression) {
|
|
21995
22427
|
const i18nContext = i18nContexts.get(op.context);
|
|
21996
|
-
const index = expressionIndices.get(op
|
|
21997
|
-
const subTemplateIndex = subTemplateIndicies.get(op.
|
|
22428
|
+
const index = expressionIndices.get(referenceIndex(op)) || 0;
|
|
22429
|
+
const subTemplateIndex = subTemplateIndicies.get(op.i18nOwner) ?? null;
|
|
21998
22430
|
// Add the expression index in the appropriate params map.
|
|
21999
22431
|
const params = op.resolutionTime === I18nParamResolutionTime.Creation ?
|
|
22000
22432
|
i18nContext.params :
|
|
@@ -22006,7 +22438,7 @@ function resolveI18nExpressionPlaceholders(job) {
|
|
|
22006
22438
|
flags: I18nParamValueFlags.ExpressionIndex
|
|
22007
22439
|
});
|
|
22008
22440
|
params.set(op.i18nPlaceholder, values);
|
|
22009
|
-
expressionIndices.set(op
|
|
22441
|
+
expressionIndices.set(referenceIndex(op), index + 1);
|
|
22010
22442
|
}
|
|
22011
22443
|
}
|
|
22012
22444
|
}
|
|
@@ -23153,11 +23585,11 @@ const phases = [
|
|
|
23153
23585
|
{ kind: CompilationJobKind.Tmpl, fn: removeContentSelectors },
|
|
23154
23586
|
{ kind: CompilationJobKind.Host, fn: parseHostStyleProperties },
|
|
23155
23587
|
{ kind: CompilationJobKind.Tmpl, fn: emitNamespaceChanges },
|
|
23156
|
-
{ kind: CompilationJobKind.Both, fn: specializeStyleBindings },
|
|
23157
|
-
{ kind: CompilationJobKind.Both, fn: specializeBindings },
|
|
23158
23588
|
{ kind: CompilationJobKind.Tmpl, fn: propagateI18nBlocks },
|
|
23159
23589
|
{ kind: CompilationJobKind.Tmpl, fn: wrapI18nIcus },
|
|
23160
23590
|
{ kind: CompilationJobKind.Tmpl, fn: createI18nContexts },
|
|
23591
|
+
{ kind: CompilationJobKind.Both, fn: specializeStyleBindings },
|
|
23592
|
+
{ kind: CompilationJobKind.Both, fn: specializeBindings },
|
|
23161
23593
|
{ kind: CompilationJobKind.Both, fn: extractAttributes },
|
|
23162
23594
|
{ kind: CompilationJobKind.Both, fn: parseExtractedStyles },
|
|
23163
23595
|
{ kind: CompilationJobKind.Tmpl, fn: removeEmptyBindings },
|
|
@@ -23166,7 +23598,10 @@ const phases = [
|
|
|
23166
23598
|
{ kind: CompilationJobKind.Tmpl, fn: generateConditionalExpressions },
|
|
23167
23599
|
{ kind: CompilationJobKind.Tmpl, fn: createPipes },
|
|
23168
23600
|
{ kind: CompilationJobKind.Tmpl, fn: configureDeferInstructions },
|
|
23169
|
-
{ kind: CompilationJobKind.Tmpl, fn:
|
|
23601
|
+
{ kind: CompilationJobKind.Tmpl, fn: convertI18nText },
|
|
23602
|
+
{ kind: CompilationJobKind.Tmpl, fn: convertI18nBindings },
|
|
23603
|
+
{ kind: CompilationJobKind.Tmpl, fn: removeUnusedI18nAttributesOps },
|
|
23604
|
+
{ kind: CompilationJobKind.Tmpl, fn: assignI18nSlotDependencies },
|
|
23170
23605
|
{ kind: CompilationJobKind.Tmpl, fn: applyI18nExpressions },
|
|
23171
23606
|
{ kind: CompilationJobKind.Tmpl, fn: createVariadicPipes },
|
|
23172
23607
|
{ kind: CompilationJobKind.Both, fn: generatePureLiteralStructures },
|
|
@@ -23196,7 +23631,6 @@ const phases = [
|
|
|
23196
23631
|
{ kind: CompilationJobKind.Tmpl, fn: collectI18nConsts },
|
|
23197
23632
|
{ kind: CompilationJobKind.Tmpl, fn: collectConstExpressions },
|
|
23198
23633
|
{ kind: CompilationJobKind.Both, fn: collectElementConsts },
|
|
23199
|
-
{ kind: CompilationJobKind.Tmpl, fn: assignI18nSlotDependencies },
|
|
23200
23634
|
{ kind: CompilationJobKind.Tmpl, fn: removeI18nContexts },
|
|
23201
23635
|
{ kind: CompilationJobKind.Both, fn: countVariables },
|
|
23202
23636
|
{ kind: CompilationJobKind.Tmpl, fn: generateAdvance },
|
|
@@ -23351,7 +23785,7 @@ function ingestHostProperty(job, property, isTextAttribute) {
|
|
|
23351
23785
|
let expression;
|
|
23352
23786
|
const ast = property.expression.ast;
|
|
23353
23787
|
if (ast instanceof Interpolation$1) {
|
|
23354
|
-
expression = new Interpolation(ast.strings, ast.expressions.map(expr => convertAst(expr, job, property.sourceSpan)));
|
|
23788
|
+
expression = new Interpolation(ast.strings, ast.expressions.map(expr => convertAst(expr, job, property.sourceSpan)), []);
|
|
23355
23789
|
}
|
|
23356
23790
|
else {
|
|
23357
23791
|
expression = convertAst(ast, job, property.sourceSpan);
|
|
@@ -23366,10 +23800,11 @@ function ingestHostProperty(job, property, isTextAttribute) {
|
|
|
23366
23800
|
bindingKind = BindingKind.Animation;
|
|
23367
23801
|
}
|
|
23368
23802
|
job.root.update.push(createBindingOp(job.root.xref, bindingKind, property.name, expression, null, SecurityContext
|
|
23369
|
-
.NONE /* TODO: what should we pass as security context? Passing NONE for now. */, isTextAttribute, false, property.sourceSpan));
|
|
23803
|
+
.NONE /* TODO: what should we pass as security context? Passing NONE for now. */, isTextAttribute, false, /* TODO: How do Host bindings handle i18n attrs? */ null, property.sourceSpan));
|
|
23370
23804
|
}
|
|
23371
23805
|
function ingestHostAttribute(job, name, value) {
|
|
23372
23806
|
const attrBinding = createBindingOp(job.root.xref, BindingKind.Attribute, name, value, null, SecurityContext.NONE, true, false,
|
|
23807
|
+
/* TODO */ null,
|
|
23373
23808
|
/* TODO: host attribute source spans */ null);
|
|
23374
23809
|
job.root.update.push(attrBinding);
|
|
23375
23810
|
}
|
|
@@ -23467,10 +23902,11 @@ function ingestTemplate(unit, tmpl) {
|
|
|
23467
23902
|
const functionNameSuffix = tagNameWithoutNamespace === null ?
|
|
23468
23903
|
'' :
|
|
23469
23904
|
prefixWithNamespace(tagNameWithoutNamespace, namespace);
|
|
23470
|
-
const
|
|
23471
|
-
|
|
23472
|
-
|
|
23473
|
-
|
|
23905
|
+
const templateKind = isPlainTemplate(tmpl) ? TemplateKind.NgTemplate : TemplateKind.Structural;
|
|
23906
|
+
const templateOp = createTemplateOp(childView.xref, templateKind, tagNameWithoutNamespace, functionNameSuffix, namespace, i18nPlaceholder, tmpl.startSourceSpan);
|
|
23907
|
+
unit.create.push(templateOp);
|
|
23908
|
+
ingestBindings(unit, templateOp, tmpl);
|
|
23909
|
+
ingestReferences(templateOp, tmpl);
|
|
23474
23910
|
ingestNodes(childView, tmpl.children);
|
|
23475
23911
|
for (const { name, value } of tmpl.variables) {
|
|
23476
23912
|
childView.contextVariables.set(name, value !== '' ? value : '$implicit');
|
|
@@ -23478,7 +23914,7 @@ function ingestTemplate(unit, tmpl) {
|
|
|
23478
23914
|
// If this is a plain template and there is an i18n message associated with it, insert i18n start
|
|
23479
23915
|
// and end ops. For structural directive templates, the i18n ops will be added when ingesting the
|
|
23480
23916
|
// element/template the directive is placed on.
|
|
23481
|
-
if (
|
|
23917
|
+
if (templateKind === TemplateKind.NgTemplate && tmpl.i18n instanceof Message) {
|
|
23482
23918
|
const id = unit.job.allocateXrefId();
|
|
23483
23919
|
OpList.insertAfter(createI18nStartOp(id, tmpl.i18n), childView.create.head);
|
|
23484
23920
|
OpList.insertBefore(createI18nEndOp(id), childView.create.tail);
|
|
@@ -23488,9 +23924,13 @@ function ingestTemplate(unit, tmpl) {
|
|
|
23488
23924
|
* Ingest a literal text node from the AST into the given `ViewCompilation`.
|
|
23489
23925
|
*/
|
|
23490
23926
|
function ingestContent(unit, content) {
|
|
23491
|
-
|
|
23927
|
+
if (content.i18n !== undefined && !(content.i18n instanceof TagPlaceholder)) {
|
|
23928
|
+
throw Error(`Unhandled i18n metadata type for element: ${content.i18n.constructor.name}`);
|
|
23929
|
+
}
|
|
23930
|
+
const attrs = content.attributes.flatMap(a => [a.name, a.value]);
|
|
23931
|
+
const op = createProjectionOp(unit.job.allocateXrefId(), content.selector, content.i18n, attrs, content.sourceSpan);
|
|
23492
23932
|
for (const attr of content.attributes) {
|
|
23493
|
-
ingestBinding(unit, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, BindingFlags.TextValue);
|
|
23933
|
+
ingestBinding(unit, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, BindingFlags.TextValue, attr.i18n);
|
|
23494
23934
|
}
|
|
23495
23935
|
unit.create.push(op);
|
|
23496
23936
|
}
|
|
@@ -23515,6 +23955,7 @@ function ingestBoundText(unit, text, i18nPlaceholders) {
|
|
|
23515
23955
|
throw Error(`Unhandled i18n metadata type for text interpolation: ${text.i18n?.constructor.name}`);
|
|
23516
23956
|
}
|
|
23517
23957
|
if (i18nPlaceholders === undefined) {
|
|
23958
|
+
// TODO: We probably can just use the placeholders field, instead of walking the AST.
|
|
23518
23959
|
i18nPlaceholders = text.i18n instanceof Container ?
|
|
23519
23960
|
text.i18n.children
|
|
23520
23961
|
.filter((node) => node instanceof Placeholder)
|
|
@@ -23530,7 +23971,7 @@ function ingestBoundText(unit, text, i18nPlaceholders) {
|
|
|
23530
23971
|
// interpolation. We copy that behavior in compatibility mode.
|
|
23531
23972
|
// TODO: is it actually correct to generate these extra maps in modern mode?
|
|
23532
23973
|
const baseSourceSpan = unit.job.compatibility ? null : text.sourceSpan;
|
|
23533
|
-
unit.update.push(createInterpolateTextOp(textXref, new Interpolation(value.strings, value.expressions.map(expr => convertAst(expr, unit.job, baseSourceSpan))
|
|
23974
|
+
unit.update.push(createInterpolateTextOp(textXref, new Interpolation(value.strings, value.expressions.map(expr => convertAst(expr, unit.job, baseSourceSpan)), i18nPlaceholders), text.sourceSpan));
|
|
23534
23975
|
}
|
|
23535
23976
|
/**
|
|
23536
23977
|
* Ingest an `@if` block into the given `ViewCompilation`.
|
|
@@ -23551,14 +23992,21 @@ function ingestIfBlock(unit, ifBlock) {
|
|
|
23551
23992
|
if (ifCase.expressionAlias !== null) {
|
|
23552
23993
|
cView.contextVariables.set(ifCase.expressionAlias.name, CTX_REF);
|
|
23553
23994
|
}
|
|
23554
|
-
|
|
23555
|
-
|
|
23995
|
+
let ifCaseI18nMeta = undefined;
|
|
23996
|
+
if (ifCase.i18n !== undefined) {
|
|
23997
|
+
if (!(ifCase.i18n instanceof BlockPlaceholder)) {
|
|
23998
|
+
throw Error(`Unhandled i18n metadata type for if block: ${ifCase.i18n?.constructor.name}`);
|
|
23999
|
+
}
|
|
24000
|
+
ifCaseI18nMeta = ifCase.i18n;
|
|
24001
|
+
}
|
|
24002
|
+
const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, tagName, 'Conditional', Namespace.HTML, ifCaseI18nMeta, ifCase.sourceSpan);
|
|
24003
|
+
unit.create.push(templateOp);
|
|
23556
24004
|
if (firstXref === null) {
|
|
23557
24005
|
firstXref = cView.xref;
|
|
23558
|
-
firstSlotHandle =
|
|
24006
|
+
firstSlotHandle = templateOp.handle;
|
|
23559
24007
|
}
|
|
23560
24008
|
const caseExpr = ifCase.expression ? convertAst(ifCase.expression, unit.job, null) : null;
|
|
23561
|
-
const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr,
|
|
24009
|
+
const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr, templateOp.xref, templateOp.handle, ifCase.expressionAlias);
|
|
23562
24010
|
conditions.push(conditionalCaseExpr);
|
|
23563
24011
|
ingestNodes(cView, ifCase.children);
|
|
23564
24012
|
}
|
|
@@ -23574,16 +24022,23 @@ function ingestSwitchBlock(unit, switchBlock) {
|
|
|
23574
24022
|
let conditions = [];
|
|
23575
24023
|
for (const switchCase of switchBlock.cases) {
|
|
23576
24024
|
const cView = unit.job.allocateView(unit.xref);
|
|
23577
|
-
|
|
23578
|
-
|
|
24025
|
+
let switchCaseI18nMeta = undefined;
|
|
24026
|
+
if (switchCase.i18n !== undefined) {
|
|
24027
|
+
if (!(switchCase.i18n instanceof BlockPlaceholder)) {
|
|
24028
|
+
throw Error(`Unhandled i18n metadata type for switch block: ${switchCase.i18n?.constructor.name}`);
|
|
24029
|
+
}
|
|
24030
|
+
switchCaseI18nMeta = switchCase.i18n;
|
|
24031
|
+
}
|
|
24032
|
+
const templateOp = createTemplateOp(cView.xref, TemplateKind.Block, null, 'Case', Namespace.HTML, switchCaseI18nMeta, switchCase.sourceSpan);
|
|
24033
|
+
unit.create.push(templateOp);
|
|
23579
24034
|
if (firstXref === null) {
|
|
23580
24035
|
firstXref = cView.xref;
|
|
23581
|
-
firstSlotHandle =
|
|
24036
|
+
firstSlotHandle = templateOp.handle;
|
|
23582
24037
|
}
|
|
23583
24038
|
const caseExpr = switchCase.expression ?
|
|
23584
24039
|
convertAst(switchCase.expression, unit.job, switchBlock.startSourceSpan) :
|
|
23585
24040
|
null;
|
|
23586
|
-
const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr,
|
|
24041
|
+
const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr, templateOp.xref, templateOp.handle);
|
|
23587
24042
|
conditions.push(conditionalCaseExpr);
|
|
23588
24043
|
ingestNodes(cView, switchCase.children);
|
|
23589
24044
|
}
|
|
@@ -23596,7 +24051,7 @@ function ingestDeferView(unit, suffix, children, sourceSpan) {
|
|
|
23596
24051
|
}
|
|
23597
24052
|
const secondaryView = unit.job.allocateView(unit.xref);
|
|
23598
24053
|
ingestNodes(secondaryView, children);
|
|
23599
|
-
const templateOp = createTemplateOp(secondaryView.xref, null, `Defer${suffix}`, Namespace.HTML, undefined, sourceSpan);
|
|
24054
|
+
const templateOp = createTemplateOp(secondaryView.xref, TemplateKind.Block, null, `Defer${suffix}`, Namespace.HTML, undefined, sourceSpan);
|
|
23600
24055
|
unit.create.push(templateOp);
|
|
23601
24056
|
return templateOp;
|
|
23602
24057
|
}
|
|
@@ -23691,12 +24146,7 @@ function ingestIcu(unit, icu) {
|
|
|
23691
24146
|
const xref = unit.job.allocateXrefId();
|
|
23692
24147
|
const icuNode = icu.i18n.nodes[0];
|
|
23693
24148
|
unit.create.push(createIcuStartOp(xref, icu.i18n, icuFromI18nMessage(icu.i18n).name, null));
|
|
23694
|
-
const
|
|
23695
|
-
if (expressionPlaceholder === undefined || icu.vars[expressionPlaceholder] === undefined) {
|
|
23696
|
-
throw Error('ICU should have a text binding');
|
|
23697
|
-
}
|
|
23698
|
-
ingestBoundText(unit, icu.vars[expressionPlaceholder], [expressionPlaceholder]);
|
|
23699
|
-
for (const [placeholder, text] of Object.entries(icu.placeholders)) {
|
|
24149
|
+
for (const [placeholder, text] of Object.entries({ ...icu.vars, ...icu.placeholders })) {
|
|
23700
24150
|
if (text instanceof BoundText) {
|
|
23701
24151
|
ingestBoundText(unit, text, [placeholder]);
|
|
23702
24152
|
}
|
|
@@ -23792,6 +24242,16 @@ function convertAst(ast, job, baseSourceSpan) {
|
|
|
23792
24242
|
else if (ast instanceof LiteralPrimitive) {
|
|
23793
24243
|
return literal(ast.value, undefined, convertSourceSpan(ast.span, baseSourceSpan));
|
|
23794
24244
|
}
|
|
24245
|
+
else if (ast instanceof Unary) {
|
|
24246
|
+
switch (ast.operator) {
|
|
24247
|
+
case '+':
|
|
24248
|
+
return new UnaryOperatorExpr(UnaryOperator.Plus, convertAst(ast.expr, job, baseSourceSpan), undefined, convertSourceSpan(ast.span, baseSourceSpan));
|
|
24249
|
+
case '-':
|
|
24250
|
+
return new UnaryOperatorExpr(UnaryOperator.Minus, convertAst(ast.expr, job, baseSourceSpan), undefined, convertSourceSpan(ast.span, baseSourceSpan));
|
|
24251
|
+
default:
|
|
24252
|
+
throw new Error(`AssertionError: unknown unary operator ${ast.operator}`);
|
|
24253
|
+
}
|
|
24254
|
+
}
|
|
23795
24255
|
else if (ast instanceof Binary) {
|
|
23796
24256
|
const operator = BINARY_OPERATORS.get(ast.operation);
|
|
23797
24257
|
if (operator === undefined) {
|
|
@@ -23850,6 +24310,9 @@ function convertAst(ast, job, baseSourceSpan) {
|
|
|
23850
24310
|
else if (ast instanceof EmptyExpr$1) {
|
|
23851
24311
|
return new EmptyExpr(convertSourceSpan(ast.span, baseSourceSpan));
|
|
23852
24312
|
}
|
|
24313
|
+
else if (ast instanceof PrefixNot) {
|
|
24314
|
+
return not(convertAst(ast.expression, job, baseSourceSpan), convertSourceSpan(ast.span, baseSourceSpan));
|
|
24315
|
+
}
|
|
23853
24316
|
else {
|
|
23854
24317
|
throw new Error(`Unhandled expression type "${ast.constructor.name}" in file "${baseSourceSpan?.start.file.url}"`);
|
|
23855
24318
|
}
|
|
@@ -23880,6 +24343,7 @@ function isPlainTemplate(tmpl) {
|
|
|
23880
24343
|
*/
|
|
23881
24344
|
function ingestBindings(unit, op, element) {
|
|
23882
24345
|
let flags = BindingFlags.None;
|
|
24346
|
+
let hasI18nAttributes = false;
|
|
23883
24347
|
if (element instanceof Template) {
|
|
23884
24348
|
flags |= BindingFlags.OnNgTemplateElement;
|
|
23885
24349
|
if (element instanceof Template && isPlainTemplate(element)) {
|
|
@@ -23888,10 +24352,12 @@ function ingestBindings(unit, op, element) {
|
|
|
23888
24352
|
const templateAttrFlags = flags | BindingFlags.BindingTargetsTemplate | BindingFlags.IsStructuralTemplateAttribute;
|
|
23889
24353
|
for (const attr of element.templateAttrs) {
|
|
23890
24354
|
if (attr instanceof TextAttribute) {
|
|
23891
|
-
ingestBinding(unit, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, templateAttrFlags | BindingFlags.TextValue);
|
|
24355
|
+
ingestBinding(unit, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, templateAttrFlags | BindingFlags.TextValue, attr.i18n);
|
|
24356
|
+
hasI18nAttributes ||= attr.i18n !== undefined;
|
|
23892
24357
|
}
|
|
23893
24358
|
else {
|
|
23894
|
-
ingestBinding(unit, op.xref, attr.name, attr.value, attr.type, attr.unit, attr.securityContext, attr.sourceSpan, templateAttrFlags);
|
|
24359
|
+
ingestBinding(unit, op.xref, attr.name, attr.value, attr.type, attr.unit, attr.securityContext, attr.sourceSpan, templateAttrFlags, attr.i18n);
|
|
24360
|
+
hasI18nAttributes ||= attr.i18n !== undefined;
|
|
23895
24361
|
}
|
|
23896
24362
|
}
|
|
23897
24363
|
}
|
|
@@ -23899,10 +24365,12 @@ function ingestBindings(unit, op, element) {
|
|
|
23899
24365
|
// This is only attribute TextLiteral bindings, such as `attr.foo="bar"`. This can never be
|
|
23900
24366
|
// `[attr.foo]="bar"` or `attr.foo="{{bar}}"`, both of which will be handled as inputs with
|
|
23901
24367
|
// `BindingType.Attribute`.
|
|
23902
|
-
ingestBinding(unit, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, flags | BindingFlags.TextValue);
|
|
24368
|
+
ingestBinding(unit, op.xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, flags | BindingFlags.TextValue, attr.i18n);
|
|
24369
|
+
hasI18nAttributes ||= attr.i18n !== undefined;
|
|
23903
24370
|
}
|
|
23904
24371
|
for (const input of element.inputs) {
|
|
23905
|
-
ingestBinding(unit, op.xref, input.name, input.value, input.type, input.unit, input.securityContext, input.sourceSpan, flags);
|
|
24372
|
+
ingestBinding(unit, op.xref, input.name, input.value, input.type, input.unit, input.securityContext, input.sourceSpan, flags, input.i18n);
|
|
24373
|
+
hasI18nAttributes ||= input.i18n !== undefined;
|
|
23906
24374
|
}
|
|
23907
24375
|
for (const output of element.outputs) {
|
|
23908
24376
|
let listenerOp;
|
|
@@ -23912,7 +24380,7 @@ function ingestBindings(unit, op, element) {
|
|
|
23912
24380
|
}
|
|
23913
24381
|
}
|
|
23914
24382
|
if (element instanceof Template && !isPlainTemplate(element)) {
|
|
23915
|
-
unit.create.push(createExtractedAttributeOp(op.xref, BindingKind.Property, output.name, null));
|
|
24383
|
+
unit.create.push(createExtractedAttributeOp(op.xref, BindingKind.Property, output.name, null, null));
|
|
23916
24384
|
continue;
|
|
23917
24385
|
}
|
|
23918
24386
|
listenerOp = createListenerOp(op.xref, op.handle, output.name, op.tag, output.phase, false, output.sourceSpan);
|
|
@@ -23941,6 +24409,10 @@ function ingestBindings(unit, op, element) {
|
|
|
23941
24409
|
listenerOp.handlerOps.push(createStatementOp(new ReturnStatement(returnExpr, returnExpr.sourceSpan)));
|
|
23942
24410
|
unit.create.push(listenerOp);
|
|
23943
24411
|
}
|
|
24412
|
+
// TODO: Perhaps we could do this in a phase? (It likely wouldn't change the slot indices.)
|
|
24413
|
+
if (hasI18nAttributes) {
|
|
24414
|
+
unit.create.push(createI18nAttributesOp(unit.job.allocateXrefId(), new SlotHandle(), op.xref));
|
|
24415
|
+
}
|
|
23944
24416
|
}
|
|
23945
24417
|
const BINDING_KINDS = new Map([
|
|
23946
24418
|
[0 /* e.BindingType.Property */, BindingKind.Property],
|
|
@@ -23969,22 +24441,34 @@ var BindingFlags;
|
|
|
23969
24441
|
*/
|
|
23970
24442
|
BindingFlags[BindingFlags["OnNgTemplateElement"] = 8] = "OnNgTemplateElement";
|
|
23971
24443
|
})(BindingFlags || (BindingFlags = {}));
|
|
23972
|
-
function ingestBinding(view, xref, name, value, type, unit, securityContext, sourceSpan, flags) {
|
|
24444
|
+
function ingestBinding(view, xref, name, value, type, unit, securityContext, sourceSpan, flags, i18nMeta) {
|
|
23973
24445
|
if (value instanceof ASTWithSource) {
|
|
23974
24446
|
value = value.ast;
|
|
23975
24447
|
}
|
|
24448
|
+
let i18nContext = null;
|
|
24449
|
+
if (i18nMeta !== undefined) {
|
|
24450
|
+
if (!(i18nMeta instanceof Message)) {
|
|
24451
|
+
throw Error(`Unhandled i18n metadata type for binding: ${i18nMeta.constructor.name}`);
|
|
24452
|
+
}
|
|
24453
|
+
i18nContext = view.job.allocateXrefId();
|
|
24454
|
+
view.create.push(createI18nContextOp(I18nContextKind.Attr, i18nContext, null, i18nMeta, null));
|
|
24455
|
+
}
|
|
23976
24456
|
if (flags & BindingFlags.OnNgTemplateElement && !(flags & BindingFlags.BindingTargetsTemplate) &&
|
|
23977
24457
|
type === 0 /* e.BindingType.Property */) {
|
|
23978
24458
|
// This binding only exists for later const extraction, and is not an actual binding to be
|
|
23979
24459
|
// created.
|
|
23980
|
-
view.create.push(createExtractedAttributeOp(xref, BindingKind.Property, name, null));
|
|
24460
|
+
view.create.push(createExtractedAttributeOp(xref, BindingKind.Property, name, null, i18nContext));
|
|
23981
24461
|
return;
|
|
23982
24462
|
}
|
|
23983
24463
|
let expression;
|
|
23984
24464
|
// TODO: We could easily generate source maps for subexpressions in these cases, but
|
|
23985
24465
|
// TemplateDefinitionBuilder does not. Should we do so?
|
|
23986
24466
|
if (value instanceof Interpolation$1) {
|
|
23987
|
-
|
|
24467
|
+
let i18nPlaceholders = [];
|
|
24468
|
+
if (i18nMeta !== undefined) {
|
|
24469
|
+
i18nPlaceholders = Object.keys(i18nMeta.placeholders);
|
|
24470
|
+
}
|
|
24471
|
+
expression = new Interpolation(value.strings, value.expressions.map(expr => convertAst(expr, view.job, null)), i18nPlaceholders);
|
|
23988
24472
|
}
|
|
23989
24473
|
else if (value instanceof AST) {
|
|
23990
24474
|
expression = convertAst(value, view.job, null);
|
|
@@ -23993,7 +24477,7 @@ function ingestBinding(view, xref, name, value, type, unit, securityContext, sou
|
|
|
23993
24477
|
expression = value;
|
|
23994
24478
|
}
|
|
23995
24479
|
const kind = BINDING_KINDS.get(type);
|
|
23996
|
-
view.update.push(createBindingOp(xref, kind, name, expression, unit, securityContext, !!(flags & BindingFlags.TextValue), !!(flags & BindingFlags.IsStructuralTemplateAttribute), sourceSpan));
|
|
24480
|
+
view.update.push(createBindingOp(xref, kind, name, expression, unit, securityContext, !!(flags & BindingFlags.TextValue), !!(flags & BindingFlags.IsStructuralTemplateAttribute), i18nContext, sourceSpan));
|
|
23997
24481
|
}
|
|
23998
24482
|
/**
|
|
23999
24483
|
* Process all of the local references on an element-like structure in the template AST and
|
|
@@ -24081,7 +24565,7 @@ function ingestControlFlowInsertionPoint(unit, xref, node) {
|
|
|
24081
24565
|
// and they can be used in directive matching (in the case of `Template.templateAttrs`).
|
|
24082
24566
|
if (root !== null) {
|
|
24083
24567
|
for (const attr of root.attributes) {
|
|
24084
|
-
ingestBinding(unit, xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, BindingFlags.TextValue);
|
|
24568
|
+
ingestBinding(unit, xref, attr.name, literal(attr.value), 1 /* e.BindingType.Attribute */, null, SecurityContext.NONE, attr.sourceSpan, BindingFlags.TextValue, attr.i18n);
|
|
24085
24569
|
}
|
|
24086
24570
|
const tagName = root instanceof Element$1 ? root.name : root.tagName;
|
|
24087
24571
|
// Don't pass along `ng-template` tag name since it enables directive matching.
|
|
@@ -27164,7 +27648,7 @@ class TemplateDefinitionBuilder {
|
|
|
27164
27648
|
else {
|
|
27165
27649
|
// ... otherwise we need to activate post-processing
|
|
27166
27650
|
// to replace ICU placeholders with proper values
|
|
27167
|
-
const placeholder = wrapI18nPlaceholder(`${I18N_ICU_MAPPING_PREFIX}${key}`);
|
|
27651
|
+
const placeholder = wrapI18nPlaceholder(`${I18N_ICU_MAPPING_PREFIX$1}${key}`);
|
|
27168
27652
|
params[key] = literal(placeholder);
|
|
27169
27653
|
icuMapping[key] = literalArr(refs);
|
|
27170
27654
|
}
|
|
@@ -28784,24 +29268,6 @@ class TrackByBindingScope extends BindingScope {
|
|
|
28784
29268
|
return this.componentAccessCount;
|
|
28785
29269
|
}
|
|
28786
29270
|
}
|
|
28787
|
-
/**
|
|
28788
|
-
* Creates a `CssSelector` given a tag name and a map of attributes
|
|
28789
|
-
*/
|
|
28790
|
-
function createCssSelector(elementName, attributes) {
|
|
28791
|
-
const cssSelector = new CssSelector();
|
|
28792
|
-
const elementNameNoNs = splitNsName(elementName)[1];
|
|
28793
|
-
cssSelector.setElement(elementNameNoNs);
|
|
28794
|
-
Object.getOwnPropertyNames(attributes).forEach((name) => {
|
|
28795
|
-
const nameNoNs = splitNsName(name)[1];
|
|
28796
|
-
const value = attributes[name];
|
|
28797
|
-
cssSelector.addAttribute(nameNoNs, value);
|
|
28798
|
-
if (name.toLowerCase() === 'class') {
|
|
28799
|
-
const classes = value.trim().split(/\s+/);
|
|
28800
|
-
classes.forEach(className => cssSelector.addClassName(className));
|
|
28801
|
-
}
|
|
28802
|
-
});
|
|
28803
|
-
return cssSelector;
|
|
28804
|
-
}
|
|
28805
29271
|
/**
|
|
28806
29272
|
* Creates an array of expressions out of an `ngProjectAs` attributes
|
|
28807
29273
|
* which can be added to the instruction parameters.
|
|
@@ -29542,6 +30008,8 @@ function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindin
|
|
|
29542
30008
|
}
|
|
29543
30009
|
return emitHostBindingFunction(hostJob);
|
|
29544
30010
|
}
|
|
30011
|
+
let bindingId = 0;
|
|
30012
|
+
const getNextBindingId = () => `${bindingId++}`;
|
|
29545
30013
|
const bindingContext = variable(CONTEXT_NAME);
|
|
29546
30014
|
const styleBuilder = new StylingBuilder(bindingContext);
|
|
29547
30015
|
const { styleAttr, classAttr } = hostBindingsMetadata.specialAttributes;
|
|
@@ -29594,7 +30062,7 @@ function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindin
|
|
|
29594
30062
|
for (const binding of allOtherBindings) {
|
|
29595
30063
|
// resolve literal arrays and literal objects
|
|
29596
30064
|
const value = binding.expression.visit(getValueConverter());
|
|
29597
|
-
const bindingExpr = bindingFn(bindingContext, value);
|
|
30065
|
+
const bindingExpr = bindingFn(bindingContext, value, getNextBindingId);
|
|
29598
30066
|
const { bindingName, instruction, isAttribute } = getBindingNameAndInstruction(binding);
|
|
29599
30067
|
const securityContexts = bindingParser.calcPossibleSecurityContexts(selector, bindingName, isAttribute)
|
|
29600
30068
|
.filter(context => context !== SecurityContext.NONE);
|
|
@@ -29673,10 +30141,12 @@ function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindin
|
|
|
29673
30141
|
// at the top of this method when all the input bindings were counted.
|
|
29674
30142
|
totalHostVarsCount +=
|
|
29675
30143
|
Math.max(call.allocateBindingSlots - MIN_STYLING_BINDING_SLOTS_REQUIRED, 0);
|
|
30144
|
+
const { params, stmts } = convertStylingCall(call, bindingContext, bindingFn, getNextBindingId);
|
|
30145
|
+
updateVariables.push(...stmts);
|
|
29676
30146
|
updateInstructions.push({
|
|
29677
30147
|
reference: instruction.reference,
|
|
29678
|
-
paramsOrFn:
|
|
29679
|
-
span: null
|
|
30148
|
+
paramsOrFn: params,
|
|
30149
|
+
span: null,
|
|
29680
30150
|
});
|
|
29681
30151
|
}
|
|
29682
30152
|
});
|
|
@@ -29697,11 +30167,19 @@ function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindin
|
|
|
29697
30167
|
}
|
|
29698
30168
|
return null;
|
|
29699
30169
|
}
|
|
29700
|
-
function bindingFn(implicit, value) {
|
|
29701
|
-
return convertPropertyBinding(null, implicit, value,
|
|
30170
|
+
function bindingFn(implicit, value, getNextBindingIdFn) {
|
|
30171
|
+
return convertPropertyBinding(null, implicit, value, getNextBindingIdFn());
|
|
29702
30172
|
}
|
|
29703
|
-
function convertStylingCall(call, bindingContext, bindingFn) {
|
|
29704
|
-
|
|
30173
|
+
function convertStylingCall(call, bindingContext, bindingFn, getNextBindingIdFn) {
|
|
30174
|
+
const stmts = [];
|
|
30175
|
+
const params = call.params(value => {
|
|
30176
|
+
const result = bindingFn(bindingContext, value, getNextBindingIdFn);
|
|
30177
|
+
if (Array.isArray(result.stmts) && result.stmts.length > 0) {
|
|
30178
|
+
stmts.push(...result.stmts);
|
|
30179
|
+
}
|
|
30180
|
+
return result.currValExpr;
|
|
30181
|
+
});
|
|
30182
|
+
return { params, stmts };
|
|
29705
30183
|
}
|
|
29706
30184
|
function getBindingNameAndInstruction(binding) {
|
|
29707
30185
|
let bindingName = binding.name;
|
|
@@ -30140,15 +30618,15 @@ class DirectiveBinder {
|
|
|
30140
30618
|
template.forEach(node => node.visit(this));
|
|
30141
30619
|
}
|
|
30142
30620
|
visitElement(element) {
|
|
30143
|
-
this.visitElementOrTemplate(element
|
|
30621
|
+
this.visitElementOrTemplate(element);
|
|
30144
30622
|
}
|
|
30145
30623
|
visitTemplate(template) {
|
|
30146
|
-
this.visitElementOrTemplate(
|
|
30624
|
+
this.visitElementOrTemplate(template);
|
|
30147
30625
|
}
|
|
30148
|
-
visitElementOrTemplate(
|
|
30626
|
+
visitElementOrTemplate(node) {
|
|
30149
30627
|
// First, determine the HTML shape of the node for the purpose of directive matching.
|
|
30150
30628
|
// Do this by building up a `CssSelector` for the node.
|
|
30151
|
-
const cssSelector =
|
|
30629
|
+
const cssSelector = createCssSelectorFromNode(node);
|
|
30152
30630
|
// Next, use the `SelectorMatcher` to get the list of directives on the node.
|
|
30153
30631
|
const directives = [];
|
|
30154
30632
|
this.matcher.match(cssSelector, (_selector, results) => directives.push(...results));
|
|
@@ -31277,7 +31755,7 @@ function publishFacade(global) {
|
|
|
31277
31755
|
* @description
|
|
31278
31756
|
* Entry point for all public APIs of the compiler package.
|
|
31279
31757
|
*/
|
|
31280
|
-
const VERSION = new Version('17.0.
|
|
31758
|
+
const VERSION = new Version('17.0.6');
|
|
31281
31759
|
|
|
31282
31760
|
class CompilerConfig {
|
|
31283
31761
|
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
@@ -32843,7 +33321,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
|
|
|
32843
33321
|
function compileDeclareClassMetadata(metadata) {
|
|
32844
33322
|
const definitionMap = new DefinitionMap();
|
|
32845
33323
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
32846
|
-
definitionMap.set('version', literal('17.0.
|
|
33324
|
+
definitionMap.set('version', literal('17.0.6'));
|
|
32847
33325
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
32848
33326
|
definitionMap.set('type', metadata.type);
|
|
32849
33327
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -32951,7 +33429,7 @@ function createDirectiveDefinitionMap(meta) {
|
|
|
32951
33429
|
// in 16.1 is actually used.
|
|
32952
33430
|
const minVersion = hasTransformFunctions ? MINIMUM_PARTIAL_LINKER_VERSION$5 : '14.0.0';
|
|
32953
33431
|
definitionMap.set('minVersion', literal(minVersion));
|
|
32954
|
-
definitionMap.set('version', literal('17.0.
|
|
33432
|
+
definitionMap.set('version', literal('17.0.6'));
|
|
32955
33433
|
// e.g. `type: MyDirective`
|
|
32956
33434
|
definitionMap.set('type', meta.type.value);
|
|
32957
33435
|
if (meta.isStandalone) {
|
|
@@ -33228,7 +33706,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
33228
33706
|
function compileDeclareFactoryFunction(meta) {
|
|
33229
33707
|
const definitionMap = new DefinitionMap();
|
|
33230
33708
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
33231
|
-
definitionMap.set('version', literal('17.0.
|
|
33709
|
+
definitionMap.set('version', literal('17.0.6'));
|
|
33232
33710
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33233
33711
|
definitionMap.set('type', meta.type.value);
|
|
33234
33712
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -33263,7 +33741,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
33263
33741
|
function createInjectableDefinitionMap(meta) {
|
|
33264
33742
|
const definitionMap = new DefinitionMap();
|
|
33265
33743
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
33266
|
-
definitionMap.set('version', literal('17.0.
|
|
33744
|
+
definitionMap.set('version', literal('17.0.6'));
|
|
33267
33745
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33268
33746
|
definitionMap.set('type', meta.type.value);
|
|
33269
33747
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -33314,7 +33792,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
33314
33792
|
function createInjectorDefinitionMap(meta) {
|
|
33315
33793
|
const definitionMap = new DefinitionMap();
|
|
33316
33794
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
33317
|
-
definitionMap.set('version', literal('17.0.
|
|
33795
|
+
definitionMap.set('version', literal('17.0.6'));
|
|
33318
33796
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33319
33797
|
definitionMap.set('type', meta.type.value);
|
|
33320
33798
|
definitionMap.set('providers', meta.providers);
|
|
@@ -33347,7 +33825,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
33347
33825
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
33348
33826
|
}
|
|
33349
33827
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
33350
|
-
definitionMap.set('version', literal('17.0.
|
|
33828
|
+
definitionMap.set('version', literal('17.0.6'));
|
|
33351
33829
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33352
33830
|
definitionMap.set('type', meta.type.value);
|
|
33353
33831
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -33398,7 +33876,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
33398
33876
|
function createPipeDefinitionMap(meta) {
|
|
33399
33877
|
const definitionMap = new DefinitionMap();
|
|
33400
33878
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
33401
|
-
definitionMap.set('version', literal('17.0.
|
|
33879
|
+
definitionMap.set('version', literal('17.0.6'));
|
|
33402
33880
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33403
33881
|
// e.g. `type: MyPipe`
|
|
33404
33882
|
definitionMap.set('type', meta.type.value);
|
|
@@ -33431,5 +33909,5 @@ publishFacade(_global);
|
|
|
33431
33909
|
|
|
33432
33910
|
// This file is not used to build this module. It is only used during editing
|
|
33433
33911
|
|
|
33434
|
-
export { AST, ASTWithName, ASTWithSource, AbsoluteSourceSpan, ArrayType, ArrowFunctionExpr, AstMemoryEfficientTransformer, AstTransformer, Attribute, Binary, BinaryOperator, BinaryOperatorExpr, BindingPipe, Block, BlockParameter, BoundElementProperty, BuiltinType, BuiltinTypeName, CUSTOM_ELEMENTS_SCHEMA, Call, Chain, ChangeDetectionStrategy, CommaExpr, Comment, CompilerConfig, Conditional, ConditionalExpr, ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DYNAMIC_TYPE, DeclareFunctionStmt, DeclareVarStmt, DomElementSchemaRegistry, DynamicImportExpr, EOF, Element, ElementSchemaRegistry, EmitterVisitorContext, EmptyExpr$1 as EmptyExpr, Expansion, ExpansionCase, Expression, ExpressionBinding, ExpressionStatement, ExpressionType, ExternalExpr, ExternalReference, FactoryTarget$1 as FactoryTarget, FunctionExpr, HtmlParser, HtmlTagDefinition, I18NHtmlParser, IfStmt, ImplicitReceiver, InstantiateExpr, Interpolation$1 as Interpolation, InterpolationConfig, InvokeFunctionExpr, JSDocComment, JitEvaluator, KeyedRead, KeyedWrite, LeadingComment, Lexer, LiteralArray, LiteralArrayExpr, LiteralExpr, LiteralMap, LiteralMapExpr, LiteralPrimitive, LocalizedString, MapType, MessageBundle, NONE_TYPE, NO_ERRORS_SCHEMA, NodeWithI18n, NonNullAssert, NotExpr, ParseError, ParseErrorLevel, ParseLocation, ParseSourceFile, ParseSourceSpan, ParseSpan, ParseTreeResult, ParsedEvent, ParsedProperty, ParsedPropertyType, ParsedVariable, Parser$1 as Parser, ParserError, PrefixNot, PropertyRead, PropertyWrite, R3BoundTarget, Identifiers as R3Identifiers, R3NgModuleMetadataKind, R3SelectorScopeMode, R3TargetBinder, R3TemplateDependencyKind, ReadKeyExpr, ReadPropExpr, ReadVarExpr, RecursiveAstVisitor, RecursiveVisitor, ResourceLoader, ReturnStatement, STRING_TYPE, SafeCall, SafeKeyedRead, SafePropertyRead, SelectorContext, SelectorListContext, SelectorMatcher, Serializer, SplitInterpolation, Statement, StmtModifier, TagContentType, TaggedTemplateExpr, TemplateBindingParseResult, TemplateLiteral, TemplateLiteralElement, Text, ThisReceiver, BoundAttribute as TmplAstBoundAttribute, BoundDeferredTrigger as TmplAstBoundDeferredTrigger, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Content as TmplAstContent, DeferredBlock as TmplAstDeferredBlock, DeferredBlockError as TmplAstDeferredBlockError, DeferredBlockLoading as TmplAstDeferredBlockLoading, DeferredBlockPlaceholder as TmplAstDeferredBlockPlaceholder, DeferredTrigger as TmplAstDeferredTrigger, Element$1 as TmplAstElement, ForLoopBlock as TmplAstForLoopBlock, ForLoopBlockEmpty as TmplAstForLoopBlockEmpty, HoverDeferredTrigger as TmplAstHoverDeferredTrigger, Icu$1 as TmplAstIcu, IdleDeferredTrigger as TmplAstIdleDeferredTrigger, IfBlock as TmplAstIfBlock, IfBlockBranch as TmplAstIfBlockBranch, ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger, InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger, RecursiveVisitor$1 as TmplAstRecursiveVisitor, Reference as TmplAstReference, SwitchBlock as TmplAstSwitchBlock, SwitchBlockCase as TmplAstSwitchBlockCase, Template as TmplAstTemplate, Text$3 as TmplAstText, TextAttribute as TmplAstTextAttribute, TimerDeferredTrigger as TmplAstTimerDeferredTrigger, UnknownBlock as TmplAstUnknownBlock, Variable as TmplAstVariable, ViewportDeferredTrigger as TmplAstViewportDeferredTrigger, Token, TokenType, TransplantedType, TreeError, Type, TypeModifier, TypeofExpr, Unary, UnaryOperator, UnaryOperatorExpr, VERSION, VariableBinding, Version, ViewEncapsulation, WrappedNodeExpr, WriteKeyExpr, WritePropExpr, WriteVarExpr, Xliff, Xliff2, Xmb, XmlParser, Xtb, _ParseAST, compileClassDebugInfo, compileClassMetadata, compileComponentClassMetadata, compileComponentFromMetadata, compileDeclareClassMetadata, compileDeclareComponentFromMetadata, compileDeclareDirectiveFromMetadata, compileDeclareFactoryFunction, compileDeclareInjectableFromMetadata, compileDeclareInjectorFromMetadata, compileDeclareNgModuleFromMetadata, compileDeclarePipeFromMetadata, compileDirectiveFromMetadata, compileFactoryFunction, compileInjectable, compileInjector, compileNgModule, compilePipeFromMetadata, computeMsgId, core, createInjectableType, createMayBeForwardRefExpression, devOnlyGuardedExpression, emitDistinctChangesOnlyDefaultValue, getHtmlTagDefinition, getNsPrefix, getSafePropertyAccessString, identifierName, isIdentifier, isNgContainer, isNgContent, isNgTemplate, jsDocComment, leadingComment, literal, literalMap, makeBindingParser, mergeNsAndName, output_ast as outputAst, parseHostBindings, parseTemplate, preserveWhitespacesDefault, publishFacade, r3JitTypeSourceSpan, sanitizeIdentifier, splitNsName, verifyHostBindings, visitAll };
|
|
33912
|
+
export { AST, ASTWithName, ASTWithSource, AbsoluteSourceSpan, ArrayType, ArrowFunctionExpr, AstMemoryEfficientTransformer, AstTransformer, Attribute, Binary, BinaryOperator, BinaryOperatorExpr, BindingPipe, Block, BlockParameter, BoundElementProperty, BuiltinType, BuiltinTypeName, CUSTOM_ELEMENTS_SCHEMA, Call, Chain, ChangeDetectionStrategy, CommaExpr, Comment, CompilerConfig, Conditional, ConditionalExpr, ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DYNAMIC_TYPE, DeclareFunctionStmt, DeclareVarStmt, DomElementSchemaRegistry, DynamicImportExpr, EOF, Element, ElementSchemaRegistry, EmitterVisitorContext, EmptyExpr$1 as EmptyExpr, Expansion, ExpansionCase, Expression, ExpressionBinding, ExpressionStatement, ExpressionType, ExternalExpr, ExternalReference, FactoryTarget$1 as FactoryTarget, FunctionExpr, HtmlParser, HtmlTagDefinition, I18NHtmlParser, IfStmt, ImplicitReceiver, InstantiateExpr, Interpolation$1 as Interpolation, InterpolationConfig, InvokeFunctionExpr, JSDocComment, JitEvaluator, KeyedRead, KeyedWrite, LeadingComment, Lexer, LiteralArray, LiteralArrayExpr, LiteralExpr, LiteralMap, LiteralMapExpr, LiteralPrimitive, LocalizedString, MapType, MessageBundle, NONE_TYPE, NO_ERRORS_SCHEMA, NodeWithI18n, NonNullAssert, NotExpr, ParseError, ParseErrorLevel, ParseLocation, ParseSourceFile, ParseSourceSpan, ParseSpan, ParseTreeResult, ParsedEvent, ParsedProperty, ParsedPropertyType, ParsedVariable, Parser$1 as Parser, ParserError, PrefixNot, PropertyRead, PropertyWrite, R3BoundTarget, Identifiers as R3Identifiers, R3NgModuleMetadataKind, R3SelectorScopeMode, R3TargetBinder, R3TemplateDependencyKind, ReadKeyExpr, ReadPropExpr, ReadVarExpr, RecursiveAstVisitor, RecursiveVisitor, ResourceLoader, ReturnStatement, STRING_TYPE, SafeCall, SafeKeyedRead, SafePropertyRead, SelectorContext, SelectorListContext, SelectorMatcher, Serializer, SplitInterpolation, Statement, StmtModifier, TagContentType, TaggedTemplateExpr, TemplateBindingParseResult, TemplateLiteral, TemplateLiteralElement, Text, ThisReceiver, BoundAttribute as TmplAstBoundAttribute, BoundDeferredTrigger as TmplAstBoundDeferredTrigger, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Content as TmplAstContent, DeferredBlock as TmplAstDeferredBlock, DeferredBlockError as TmplAstDeferredBlockError, DeferredBlockLoading as TmplAstDeferredBlockLoading, DeferredBlockPlaceholder as TmplAstDeferredBlockPlaceholder, DeferredTrigger as TmplAstDeferredTrigger, Element$1 as TmplAstElement, ForLoopBlock as TmplAstForLoopBlock, ForLoopBlockEmpty as TmplAstForLoopBlockEmpty, HoverDeferredTrigger as TmplAstHoverDeferredTrigger, Icu$1 as TmplAstIcu, IdleDeferredTrigger as TmplAstIdleDeferredTrigger, IfBlock as TmplAstIfBlock, IfBlockBranch as TmplAstIfBlockBranch, ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger, InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger, RecursiveVisitor$1 as TmplAstRecursiveVisitor, Reference as TmplAstReference, SwitchBlock as TmplAstSwitchBlock, SwitchBlockCase as TmplAstSwitchBlockCase, Template as TmplAstTemplate, Text$3 as TmplAstText, TextAttribute as TmplAstTextAttribute, TimerDeferredTrigger as TmplAstTimerDeferredTrigger, UnknownBlock as TmplAstUnknownBlock, Variable as TmplAstVariable, ViewportDeferredTrigger as TmplAstViewportDeferredTrigger, Token, TokenType, TransplantedType, TreeError, Type, TypeModifier, TypeofExpr, Unary, UnaryOperator, UnaryOperatorExpr, VERSION, VariableBinding, Version, ViewEncapsulation, WrappedNodeExpr, WriteKeyExpr, WritePropExpr, WriteVarExpr, Xliff, Xliff2, Xmb, XmlParser, Xtb, _ParseAST, compileClassDebugInfo, compileClassMetadata, compileComponentClassMetadata, compileComponentFromMetadata, compileDeclareClassMetadata, compileDeclareComponentFromMetadata, compileDeclareDirectiveFromMetadata, compileDeclareFactoryFunction, compileDeclareInjectableFromMetadata, compileDeclareInjectorFromMetadata, compileDeclareNgModuleFromMetadata, compileDeclarePipeFromMetadata, compileDirectiveFromMetadata, compileFactoryFunction, compileInjectable, compileInjector, compileNgModule, compilePipeFromMetadata, computeMsgId, core, createCssSelectorFromNode, createInjectableType, createMayBeForwardRefExpression, devOnlyGuardedExpression, emitDistinctChangesOnlyDefaultValue, getHtmlTagDefinition, getNsPrefix, getSafePropertyAccessString, identifierName, isIdentifier, isNgContainer, isNgContent, isNgTemplate, jsDocComment, leadingComment, literal, literalMap, makeBindingParser, mergeNsAndName, output_ast as outputAst, parseHostBindings, parseTemplate, preserveWhitespacesDefault, publishFacade, r3JitTypeSourceSpan, sanitizeIdentifier, splitNsName, verifyHostBindings, visitAll };
|
|
33435
33913
|
//# sourceMappingURL=compiler.mjs.map
|