@angular/compiler 17.0.0-next.8 → 17.0.0-rc.0
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/ml_parser/html_tags.mjs +4 -4
- 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/shadow_css.mjs +10 -5
- package/esm2022/src/template/pipeline/ir/src/enums.mjs +25 -1
- package/esm2022/src/template/pipeline/ir/src/expression.mjs +3 -1
- package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +15 -1
- package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +14 -2
- package/esm2022/src/template/pipeline/src/emit.mjs +5 -3
- package/esm2022/src/template/pipeline/src/ingest.mjs +41 -8
- package/esm2022/src/template/pipeline/src/instruction.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/generate_variables.mjs +1 -2
- package/esm2022/src/template/pipeline/src/phases/i18n_const_collection.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/i18n_message_extraction.mjs +14 -4
- package/esm2022/src/template/pipeline/src/phases/i18n_text_extraction.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/icu_extraction.mjs +53 -0
- package/esm2022/src/template/pipeline/src/phases/local_refs.mjs +1 -2
- package/esm2022/src/template/pipeline/src/phases/namespace.mjs +2 -2
- package/esm2022/src/template/pipeline/src/phases/naming.mjs +3 -2
- package/esm2022/src/template/pipeline/src/phases/ng_container.mjs +1 -6
- package/esm2022/src/template/pipeline/src/phases/reify.mjs +1 -1
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_placeholders.mjs +134 -36
- package/esm2022/src/template/pipeline/src/phases/resolve_sanitizers.mjs +2 -3
- package/esm2022/src/template/pipeline/src/phases/wrap_icus.mjs +34 -0
- package/esm2022/src/version.mjs +1 -1
- package/fesm2022/compiler.mjs +338 -108
- package/fesm2022/compiler.mjs.map +1 -1
- package/index.d.ts +1 -1
- package/package.json +2 -2
- package/esm2022/src/template/pipeline/src/phases/propagate_i18n_placeholders.mjs +0 -39
package/fesm2022/compiler.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v17.0.0-
|
|
2
|
+
* @license Angular v17.0.0-rc.0
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -8317,7 +8317,7 @@ class ShadowCss {
|
|
|
8317
8317
|
// (ie: ".\fc ber" for ".über") is not a separator between 2 selectors
|
|
8318
8318
|
// also keep in mind that backslashes are replaced by a placeholder by SafeSelector
|
|
8319
8319
|
// These escaped selectors happen for example when esbuild runs with optimization.minify.
|
|
8320
|
-
if (part.match(
|
|
8320
|
+
if (part.match(/__esc-ph-(\d+)__/) && selector[res.index + 1]?.match(/[a-fA-F\d]/)) {
|
|
8321
8321
|
continue;
|
|
8322
8322
|
}
|
|
8323
8323
|
shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1;
|
|
@@ -8348,7 +8348,13 @@ class SafeSelector {
|
|
|
8348
8348
|
// pseudo-class, but writing `.foo\:blue` will match, because the colon was escaped.
|
|
8349
8349
|
// Replace all escape sequences (`\` followed by a character) with a placeholder so
|
|
8350
8350
|
// that our handling of pseudo-selectors doesn't mess with them.
|
|
8351
|
-
|
|
8351
|
+
// Escaped characters have a specific placeholder so they can be detected separately.
|
|
8352
|
+
selector = selector.replace(/(\\.)/g, (_, keep) => {
|
|
8353
|
+
const replaceBy = `__esc-ph-${this.index}__`;
|
|
8354
|
+
this.placeholders.push(keep);
|
|
8355
|
+
this.index++;
|
|
8356
|
+
return replaceBy;
|
|
8357
|
+
});
|
|
8352
8358
|
// Replaces the expression in `:nth-child(2n + 1)` with a placeholder.
|
|
8353
8359
|
// WS and "+" would otherwise be interpreted as selector separators.
|
|
8354
8360
|
this._content = selector.replace(/(:nth-[-\w]+)(\([^)]+\))/g, (_, pseudo, exp) => {
|
|
@@ -8359,7 +8365,7 @@ class SafeSelector {
|
|
|
8359
8365
|
});
|
|
8360
8366
|
}
|
|
8361
8367
|
restore(content) {
|
|
8362
|
-
return content.replace(
|
|
8368
|
+
return content.replace(/__(?:ph|esc-ph)-(\d+)__/g, (_ph, index) => this.placeholders[+index]);
|
|
8363
8369
|
}
|
|
8364
8370
|
content() {
|
|
8365
8371
|
return this._content;
|
|
@@ -8411,7 +8417,6 @@ const _commentRe = /\/\*[\s\S]*?\*\//g;
|
|
|
8411
8417
|
const _commentWithHashRe = /\/\*\s*#\s*source(Mapping)?URL=/g;
|
|
8412
8418
|
const COMMENT_PLACEHOLDER = '%COMMENT%';
|
|
8413
8419
|
const _commentWithHashPlaceHolderRe = new RegExp(COMMENT_PLACEHOLDER, 'g');
|
|
8414
|
-
const _placeholderRe = /__ph-(\d+)__/g;
|
|
8415
8420
|
const BLOCK_PLACEHOLDER = '%BLOCK%';
|
|
8416
8421
|
const _ruleRe = new RegExp(`(\\s*(?:${COMMENT_PLACEHOLDER}\\s*)*)([^;\\{\\}]+?)(\\s*)((?:{%BLOCK%}?\\s*;?)|(?:\\s*;))`, 'g');
|
|
8417
8422
|
const CONTENT_PAIRS = new Map([['{', '}']]);
|
|
@@ -8841,6 +8846,14 @@ var OpKind;
|
|
|
8841
8846
|
* An instruction that applies a set of i18n expressions.
|
|
8842
8847
|
*/
|
|
8843
8848
|
OpKind[OpKind["I18nApply"] = 38] = "I18nApply";
|
|
8849
|
+
/**
|
|
8850
|
+
* An instruction to create an ICU expression.
|
|
8851
|
+
*/
|
|
8852
|
+
OpKind[OpKind["Icu"] = 39] = "Icu";
|
|
8853
|
+
/**
|
|
8854
|
+
* An instruction to update an ICU expression.
|
|
8855
|
+
*/
|
|
8856
|
+
OpKind[OpKind["IcuUpdate"] = 40] = "IcuUpdate";
|
|
8844
8857
|
})(OpKind || (OpKind = {}));
|
|
8845
8858
|
/**
|
|
8846
8859
|
* Distinguishes different kinds of IR expressions.
|
|
@@ -9019,6 +9032,22 @@ var BindingKind;
|
|
|
9019
9032
|
*/
|
|
9020
9033
|
BindingKind[BindingKind["Animation"] = 6] = "Animation";
|
|
9021
9034
|
})(BindingKind || (BindingKind = {}));
|
|
9035
|
+
/**
|
|
9036
|
+
* Enumeration of possible times i18n params can be resolved.
|
|
9037
|
+
*/
|
|
9038
|
+
var I18nParamResolutionTime;
|
|
9039
|
+
(function (I18nParamResolutionTime) {
|
|
9040
|
+
/**
|
|
9041
|
+
* Param is resolved at message creation time. Most params should be resolved at message creation
|
|
9042
|
+
* time. However, ICU params need to be handled in post-processing.
|
|
9043
|
+
*/
|
|
9044
|
+
I18nParamResolutionTime[I18nParamResolutionTime["Creation"] = 0] = "Creation";
|
|
9045
|
+
/**
|
|
9046
|
+
* Param is resolved during post-processing. This should be used for params who's value comes from
|
|
9047
|
+
* an ICU.
|
|
9048
|
+
*/
|
|
9049
|
+
I18nParamResolutionTime[I18nParamResolutionTime["Postproccessing"] = 1] = "Postproccessing";
|
|
9050
|
+
})(I18nParamResolutionTime || (I18nParamResolutionTime = {}));
|
|
9022
9051
|
|
|
9023
9052
|
/**
|
|
9024
9053
|
* Marker symbol for `ConsumesSlotOpTrait`.
|
|
@@ -9317,13 +9346,14 @@ function createConditionalOp(target, test, conditions, sourceSpan) {
|
|
|
9317
9346
|
/**
|
|
9318
9347
|
* Create an i18n expression op.
|
|
9319
9348
|
*/
|
|
9320
|
-
function createI18nExpressionOp(owner, expression, i18nPlaceholder, sourceSpan) {
|
|
9349
|
+
function createI18nExpressionOp(owner, expression, i18nPlaceholder, resolutionTime, sourceSpan) {
|
|
9321
9350
|
return {
|
|
9322
9351
|
kind: OpKind.I18nExpression,
|
|
9323
9352
|
owner,
|
|
9324
9353
|
target: owner,
|
|
9325
9354
|
expression,
|
|
9326
9355
|
i18nPlaceholder,
|
|
9356
|
+
resolutionTime,
|
|
9327
9357
|
sourceSpan,
|
|
9328
9358
|
...NEW_OP,
|
|
9329
9359
|
...TRAIT_CONSUMES_VARS,
|
|
@@ -9342,6 +9372,17 @@ function createI18nApplyOp(target, sourceSpan) {
|
|
|
9342
9372
|
...TRAIT_USES_SLOT_INDEX,
|
|
9343
9373
|
};
|
|
9344
9374
|
}
|
|
9375
|
+
/**
|
|
9376
|
+
* Creates an op to update an ICU expression.
|
|
9377
|
+
*/
|
|
9378
|
+
function createIcuUpdateOp(xref, sourceSpan) {
|
|
9379
|
+
return {
|
|
9380
|
+
kind: OpKind.IcuUpdate,
|
|
9381
|
+
xref,
|
|
9382
|
+
sourceSpan,
|
|
9383
|
+
...NEW_OP,
|
|
9384
|
+
};
|
|
9385
|
+
}
|
|
9345
9386
|
|
|
9346
9387
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
9347
9388
|
/**
|
|
@@ -10064,6 +10105,8 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
10064
10105
|
case OpKind.Advance:
|
|
10065
10106
|
case OpKind.Namespace:
|
|
10066
10107
|
case OpKind.I18nApply:
|
|
10108
|
+
case OpKind.Icu:
|
|
10109
|
+
case OpKind.IcuUpdate:
|
|
10067
10110
|
// These operations contain no expressions.
|
|
10068
10111
|
break;
|
|
10069
10112
|
default:
|
|
@@ -10662,8 +10705,10 @@ function createI18nStartOp(xref, message, root) {
|
|
|
10662
10705
|
root: root ?? xref,
|
|
10663
10706
|
message,
|
|
10664
10707
|
params: new Map(),
|
|
10708
|
+
postprocessingParams: new Map(),
|
|
10665
10709
|
messageIndex: null,
|
|
10666
10710
|
subTemplateIndex: null,
|
|
10711
|
+
needsPostprocessing: false,
|
|
10667
10712
|
...NEW_OP,
|
|
10668
10713
|
...TRAIT_CONSUMES_SLOT,
|
|
10669
10714
|
};
|
|
@@ -10678,6 +10723,18 @@ function createI18nEndOp(xref) {
|
|
|
10678
10723
|
...NEW_OP,
|
|
10679
10724
|
};
|
|
10680
10725
|
}
|
|
10726
|
+
/**
|
|
10727
|
+
* Creates an op to create an ICU expression.
|
|
10728
|
+
*/
|
|
10729
|
+
function createIcuOp(xref, message, sourceSpan) {
|
|
10730
|
+
return {
|
|
10731
|
+
kind: OpKind.Icu,
|
|
10732
|
+
xref,
|
|
10733
|
+
message,
|
|
10734
|
+
sourceSpan,
|
|
10735
|
+
...NEW_OP,
|
|
10736
|
+
};
|
|
10737
|
+
}
|
|
10681
10738
|
function literalOrArrayLiteral$1(value) {
|
|
10682
10739
|
if (Array.isArray(value)) {
|
|
10683
10740
|
return literalArr(value.map(literalOrArrayLiteral$1));
|
|
@@ -11986,7 +12043,6 @@ function getScopeForView(view, parent) {
|
|
|
11986
12043
|
}
|
|
11987
12044
|
for (const op of view.create) {
|
|
11988
12045
|
switch (op.kind) {
|
|
11989
|
-
case OpKind.Element:
|
|
11990
12046
|
case OpKind.ElementStart:
|
|
11991
12047
|
case OpKind.Template:
|
|
11992
12048
|
if (!Array.isArray(op.localRefs)) {
|
|
@@ -12154,7 +12210,7 @@ function phaseI18nConstCollection(job) {
|
|
|
12154
12210
|
// Assign const index to i18n ops that messages were extracted from.
|
|
12155
12211
|
for (const unit of job.units) {
|
|
12156
12212
|
for (const op of unit.create) {
|
|
12157
|
-
if (op.kind === OpKind.I18nStart
|
|
12213
|
+
if (op.kind === OpKind.I18nStart) {
|
|
12158
12214
|
op.messageIndex = messageConstIndices[op.root];
|
|
12159
12215
|
}
|
|
12160
12216
|
}
|
|
@@ -14451,7 +14507,7 @@ let TAG_DEFINITIONS;
|
|
|
14451
14507
|
function getHtmlTagDefinition(tagName) {
|
|
14452
14508
|
if (!TAG_DEFINITIONS) {
|
|
14453
14509
|
DEFAULT_TAG_DEFINITION = new HtmlTagDefinition({ canSelfClose: true });
|
|
14454
|
-
TAG_DEFINITIONS = {
|
|
14510
|
+
TAG_DEFINITIONS = Object.assign(Object.create(null), {
|
|
14455
14511
|
'base': new HtmlTagDefinition({ isVoid: true }),
|
|
14456
14512
|
'meta': new HtmlTagDefinition({ isVoid: true }),
|
|
14457
14513
|
'area': new HtmlTagDefinition({ isVoid: true }),
|
|
@@ -14513,9 +14569,9 @@ function getHtmlTagDefinition(tagName) {
|
|
|
14513
14569
|
contentType: { default: TagContentType.ESCAPABLE_RAW_TEXT, svg: TagContentType.PARSABLE_DATA }
|
|
14514
14570
|
}),
|
|
14515
14571
|
'textarea': new HtmlTagDefinition({ contentType: TagContentType.ESCAPABLE_RAW_TEXT, ignoreFirstLf: true }),
|
|
14516
|
-
};
|
|
14572
|
+
});
|
|
14517
14573
|
new DomElementSchemaRegistry().allKnownElementNames().forEach(knownTagName => {
|
|
14518
|
-
if (!TAG_DEFINITIONS
|
|
14574
|
+
if (!TAG_DEFINITIONS[knownTagName] && getNsPrefix(knownTagName) === null) {
|
|
14519
14575
|
TAG_DEFINITIONS[knownTagName] = new HtmlTagDefinition({ canSelfClose: false });
|
|
14520
14576
|
}
|
|
14521
14577
|
});
|
|
@@ -19053,7 +19109,7 @@ function phaseI18nMessageExtraction(job) {
|
|
|
19053
19109
|
const fileBasedI18nSuffix = job.relativeContextFilePath.replace(/[^A-Za-z0-9]/g, '_').toUpperCase() + '_';
|
|
19054
19110
|
for (const unit of job.units) {
|
|
19055
19111
|
for (const op of unit.create) {
|
|
19056
|
-
if (
|
|
19112
|
+
if (op.kind === OpKind.I18nStart) {
|
|
19057
19113
|
// Only extract messages from root i18n ops, not sub-template ones.
|
|
19058
19114
|
if (op.xref === op.root) {
|
|
19059
19115
|
// Sort the params map to match the ordering in TemplateDefinitionBuilder.
|
|
@@ -19063,8 +19119,17 @@ function phaseI18nMessageExtraction(job) {
|
|
|
19063
19119
|
// const to start with `MSG_`. We define a variable starting with `MSG_` just for the
|
|
19064
19120
|
// `goog.getMsg` call
|
|
19065
19121
|
const closureVar = i18nGenerateClosureVar(job.pool, op.message.id, fileBasedI18nSuffix, job.i18nUseExternalIds);
|
|
19066
|
-
|
|
19067
|
-
|
|
19122
|
+
let transformFn = undefined;
|
|
19123
|
+
// If nescessary, add a post-processing step and resolve any placeholder params that are
|
|
19124
|
+
// set in post-processing.
|
|
19125
|
+
if (op.needsPostprocessing) {
|
|
19126
|
+
const extraTransformFnParams = [];
|
|
19127
|
+
if (op.postprocessingParams.size > 0) {
|
|
19128
|
+
extraTransformFnParams.push(literalMap([...op.postprocessingParams.entries()].map(([key, value]) => ({ key, value, quoted: true }))));
|
|
19129
|
+
}
|
|
19130
|
+
transformFn = (expr) => importExpr(Identifiers.i18nPostprocess).callFn([expr, ...extraTransformFnParams]);
|
|
19131
|
+
}
|
|
19132
|
+
const statements = getTranslationDeclStmts$1(op.message, mainVar, closureVar, params, transformFn);
|
|
19068
19133
|
unit.create.push(createExtractedMessageOp(op.xref, mainVar, statements));
|
|
19069
19134
|
}
|
|
19070
19135
|
}
|
|
@@ -19177,7 +19242,7 @@ function phaseI18nTextExtraction(job) {
|
|
|
19177
19242
|
for (let i = 0; i < op.interpolation.expressions.length; i++) {
|
|
19178
19243
|
const expr = op.interpolation.expressions[i];
|
|
19179
19244
|
const placeholder = op.i18nPlaceholders[i];
|
|
19180
|
-
ops.push(createI18nExpressionOp(i18nBlockId, expr, placeholder, expr.sourceSpan ?? op.sourceSpan));
|
|
19245
|
+
ops.push(createI18nExpressionOp(i18nBlockId, expr, placeholder.name, I18nParamResolutionTime.Creation, expr.sourceSpan ?? op.sourceSpan));
|
|
19181
19246
|
}
|
|
19182
19247
|
if (ops.length > 0) {
|
|
19183
19248
|
// ops.push(ir.createI18nApplyOp(i18nBlockId, op.i18nPlaceholders, op.sourceSpan));
|
|
@@ -19189,6 +19254,50 @@ function phaseI18nTextExtraction(job) {
|
|
|
19189
19254
|
}
|
|
19190
19255
|
}
|
|
19191
19256
|
|
|
19257
|
+
/**
|
|
19258
|
+
* Extracts ICUs into i18n expressions.
|
|
19259
|
+
*/
|
|
19260
|
+
function phaseIcuExtraction(job) {
|
|
19261
|
+
for (const unit of job.units) {
|
|
19262
|
+
// Build a map of ICU to the i18n block they belong to, then remove the `Icu` ops.
|
|
19263
|
+
const icus = new Map();
|
|
19264
|
+
let currentI18nId = null;
|
|
19265
|
+
for (const op of unit.create) {
|
|
19266
|
+
switch (op.kind) {
|
|
19267
|
+
case OpKind.I18nStart:
|
|
19268
|
+
currentI18nId = op.xref;
|
|
19269
|
+
break;
|
|
19270
|
+
case OpKind.I18nEnd:
|
|
19271
|
+
currentI18nId = null;
|
|
19272
|
+
break;
|
|
19273
|
+
case OpKind.Icu:
|
|
19274
|
+
if (currentI18nId === null) {
|
|
19275
|
+
throw Error('Unexpected ICU outside of an i18n block.');
|
|
19276
|
+
}
|
|
19277
|
+
icus.set(op.xref, { message: op.message, i18nBlockId: currentI18nId });
|
|
19278
|
+
OpList.remove(op);
|
|
19279
|
+
break;
|
|
19280
|
+
}
|
|
19281
|
+
}
|
|
19282
|
+
// Replace the `IcuUpdate` ops with `i18nExpr` ops.
|
|
19283
|
+
for (const op of unit.update) {
|
|
19284
|
+
switch (op.kind) {
|
|
19285
|
+
case OpKind.IcuUpdate:
|
|
19286
|
+
const { message, i18nBlockId } = icus.get(op.xref);
|
|
19287
|
+
const icuNode = message.nodes.find((n) => n instanceof Icu);
|
|
19288
|
+
if (icuNode === undefined) {
|
|
19289
|
+
throw Error('Could not find ICU in i18n AST');
|
|
19290
|
+
}
|
|
19291
|
+
if (icuNode.expressionPlaceholder === undefined) {
|
|
19292
|
+
throw Error('ICU is missing an i18n placeholder');
|
|
19293
|
+
}
|
|
19294
|
+
OpList.replace(op, createI18nExpressionOp(i18nBlockId, new LexicalReadExpr(icuNode.expression), icuNode.expressionPlaceholder, I18nParamResolutionTime.Postproccessing, null));
|
|
19295
|
+
break;
|
|
19296
|
+
}
|
|
19297
|
+
}
|
|
19298
|
+
}
|
|
19299
|
+
}
|
|
19300
|
+
|
|
19192
19301
|
/**
|
|
19193
19302
|
* Lifts local reference declarations on element-like structures within each view into an entry in
|
|
19194
19303
|
* the `consts` array for the whole component.
|
|
@@ -19198,7 +19307,6 @@ function phaseLocalRefs(job) {
|
|
|
19198
19307
|
for (const op of unit.create) {
|
|
19199
19308
|
switch (op.kind) {
|
|
19200
19309
|
case OpKind.ElementStart:
|
|
19201
|
-
case OpKind.Element:
|
|
19202
19310
|
case OpKind.Template:
|
|
19203
19311
|
if (!Array.isArray(op.localRefs)) {
|
|
19204
19312
|
throw new Error(`AssertionError: expected localRefs to be an array still`);
|
|
@@ -19231,7 +19339,7 @@ function phaseNamespace(job) {
|
|
|
19231
19339
|
for (const unit of job.units) {
|
|
19232
19340
|
let activeNamespace = Namespace.HTML;
|
|
19233
19341
|
for (const op of unit.create) {
|
|
19234
|
-
if (op.kind !== OpKind.
|
|
19342
|
+
if (op.kind !== OpKind.ElementStart) {
|
|
19235
19343
|
continue;
|
|
19236
19344
|
}
|
|
19237
19345
|
if (op.namespace !== activeNamespace) {
|
|
@@ -19376,7 +19484,8 @@ function addNamesToView(unit, baseName, state, compatibility) {
|
|
|
19376
19484
|
if (op.slot === null) {
|
|
19377
19485
|
throw new Error(`Expected slot to be assigned`);
|
|
19378
19486
|
}
|
|
19379
|
-
|
|
19487
|
+
const tagToken = op.tag === null ? '' : '_' + prefixWithNamespace(op.tag, op.namespace);
|
|
19488
|
+
addNamesToView(childView, `${baseName}${tagToken}_${op.slot}`, state, compatibility);
|
|
19380
19489
|
break;
|
|
19381
19490
|
case OpKind.StyleProp:
|
|
19382
19491
|
op.name = normalizeStylePropName(op.name);
|
|
@@ -19510,11 +19619,6 @@ function phaseNgContainer(job) {
|
|
|
19510
19619
|
for (const unit of job.units) {
|
|
19511
19620
|
const updatedElementXrefs = new Set();
|
|
19512
19621
|
for (const op of unit.create) {
|
|
19513
|
-
if (op.kind === OpKind.Element && op.tag === CONTAINER_TAG) {
|
|
19514
|
-
// Transmute the `Element` instruction to `Container`.
|
|
19515
|
-
op.kind = OpKind.Container;
|
|
19516
|
-
updatedElementXrefs.add(op.xref);
|
|
19517
|
-
}
|
|
19518
19622
|
if (op.kind === OpKind.ElementStart && op.tag === CONTAINER_TAG) {
|
|
19519
19623
|
// Transmute the `ElementStart` instruction to `ContainerStart`.
|
|
19520
19624
|
op.kind = OpKind.ContainerStart;
|
|
@@ -19847,37 +19951,6 @@ function wrapTemplateWithI18n(unit, parentI18n) {
|
|
|
19847
19951
|
}
|
|
19848
19952
|
}
|
|
19849
19953
|
|
|
19850
|
-
function phasePropagateI18nPlaceholders(job) {
|
|
19851
|
-
// Get all of the i18n ops.
|
|
19852
|
-
const i18nOps = new Map();
|
|
19853
|
-
for (const unit of job.units) {
|
|
19854
|
-
for (const op of unit.create) {
|
|
19855
|
-
if (op.kind === OpKind.I18nStart) {
|
|
19856
|
-
i18nOps.set(op.xref, op);
|
|
19857
|
-
}
|
|
19858
|
-
}
|
|
19859
|
-
}
|
|
19860
|
-
// Propagate i18n params from sub-templates up to the root i18n op.
|
|
19861
|
-
for (const op of i18nOps.values()) {
|
|
19862
|
-
if (op.xref !== op.root) {
|
|
19863
|
-
const rootOp = i18nOps.get(op.root);
|
|
19864
|
-
for (const [placeholder, value] of op.params) {
|
|
19865
|
-
rootOp.params.set(placeholder, value);
|
|
19866
|
-
}
|
|
19867
|
-
}
|
|
19868
|
-
}
|
|
19869
|
-
// Validate the root i18n ops have all placeholders filled in.
|
|
19870
|
-
for (const op of i18nOps.values()) {
|
|
19871
|
-
if (op.xref === op.root) {
|
|
19872
|
-
for (const placeholder in op.message.placeholders) {
|
|
19873
|
-
if (!op.params.has(placeholder)) {
|
|
19874
|
-
throw Error(`Failed to resolve i18n placeholder: ${placeholder}`);
|
|
19875
|
-
}
|
|
19876
|
-
}
|
|
19877
|
-
}
|
|
19878
|
-
}
|
|
19879
|
-
}
|
|
19880
|
-
|
|
19881
19954
|
function phasePureFunctionExtraction(job) {
|
|
19882
19955
|
for (const view of job.units) {
|
|
19883
19956
|
for (const op of view.ops()) {
|
|
@@ -20008,7 +20081,7 @@ function elementContainerEnd() {
|
|
|
20008
20081
|
}
|
|
20009
20082
|
function template(slot, templateFnRef, decls, vars, tag, constIndex, sourceSpan) {
|
|
20010
20083
|
const args = [literal(slot), templateFnRef, literal(decls), literal(vars)];
|
|
20011
|
-
if (tag !== null) {
|
|
20084
|
+
if (tag !== null || constIndex !== null) {
|
|
20012
20085
|
args.push(literal(tag));
|
|
20013
20086
|
if (constIndex !== null) {
|
|
20014
20087
|
args.push(literal(constIndex));
|
|
@@ -20881,6 +20954,10 @@ const LIST_END_MARKER = ']';
|
|
|
20881
20954
|
* Delimiter used to separate multiple values in a list.
|
|
20882
20955
|
*/
|
|
20883
20956
|
const LIST_DELIMITER = '|';
|
|
20957
|
+
/**
|
|
20958
|
+
* Flags that describe what an i18n param value. These determine how the value is serialized into
|
|
20959
|
+
* the final map.
|
|
20960
|
+
*/
|
|
20884
20961
|
var I18nParamValueFlags;
|
|
20885
20962
|
(function (I18nParamValueFlags) {
|
|
20886
20963
|
I18nParamValueFlags[I18nParamValueFlags["None"] = 0] = "None";
|
|
@@ -20893,10 +20970,13 @@ var I18nParamValueFlags;
|
|
|
20893
20970
|
*/
|
|
20894
20971
|
I18nParamValueFlags[I18nParamValueFlags["TemplateTag"] = 2] = "TemplateTag";
|
|
20895
20972
|
/**
|
|
20896
|
-
* This value represents the
|
|
20897
|
-
* TemplateTag)
|
|
20973
|
+
* This value represents the opening of a tag.
|
|
20898
20974
|
*/
|
|
20899
|
-
I18nParamValueFlags[I18nParamValueFlags["
|
|
20975
|
+
I18nParamValueFlags[I18nParamValueFlags["OpenTag"] = 4] = "OpenTag";
|
|
20976
|
+
/**
|
|
20977
|
+
* This value represents the closing of a tag.
|
|
20978
|
+
*/
|
|
20979
|
+
I18nParamValueFlags[I18nParamValueFlags["CloseTag"] = 8] = "CloseTag";
|
|
20900
20980
|
})(I18nParamValueFlags || (I18nParamValueFlags = {}));
|
|
20901
20981
|
/**
|
|
20902
20982
|
* Represents the complete i18n params map for an i18n op.
|
|
@@ -20908,9 +20988,9 @@ class I18nPlaceholderParams {
|
|
|
20908
20988
|
/**
|
|
20909
20989
|
* Adds a new value to the params map.
|
|
20910
20990
|
*/
|
|
20911
|
-
addValue(placeholder, value, subTemplateIndex, flags) {
|
|
20991
|
+
addValue(placeholder, value, subTemplateIndex, resolutionTime, flags) {
|
|
20912
20992
|
const placeholderValues = this.values.get(placeholder) ?? [];
|
|
20913
|
-
placeholderValues.push({ value, subTemplateIndex, flags });
|
|
20993
|
+
placeholderValues.push({ value, subTemplateIndex, resolutionTime, flags });
|
|
20914
20994
|
this.values.set(placeholder, placeholderValues);
|
|
20915
20995
|
}
|
|
20916
20996
|
/**
|
|
@@ -20918,13 +20998,49 @@ class I18nPlaceholderParams {
|
|
|
20918
20998
|
*/
|
|
20919
20999
|
saveToOp(op) {
|
|
20920
21000
|
for (const [placeholder, placeholderValues] of this.values) {
|
|
20921
|
-
|
|
21001
|
+
// We need to run post-processing for any 1i8n ops that contain parameters with more than
|
|
21002
|
+
// one value, even if there are no parameters resolved at post-processing time.
|
|
21003
|
+
const creationValues = placeholderValues.filter(({ resolutionTime }) => resolutionTime === I18nParamResolutionTime.Creation);
|
|
21004
|
+
if (creationValues.length > 1) {
|
|
21005
|
+
op.needsPostprocessing = true;
|
|
21006
|
+
}
|
|
21007
|
+
// Save creation time params to op.
|
|
21008
|
+
const serializedCreationValues = this.serializeValues(creationValues);
|
|
21009
|
+
if (serializedCreationValues !== null) {
|
|
21010
|
+
op.params.set(placeholder, literal(serializedCreationValues));
|
|
21011
|
+
}
|
|
21012
|
+
// Save post-processing time params to op.
|
|
21013
|
+
const serializedPostprocessingValues = this.serializeValues(placeholderValues.filter(({ resolutionTime }) => resolutionTime === I18nParamResolutionTime.Postproccessing));
|
|
21014
|
+
if (serializedPostprocessingValues !== null) {
|
|
21015
|
+
op.needsPostprocessing = true;
|
|
21016
|
+
op.postprocessingParams.set(placeholder, literal(serializedPostprocessingValues));
|
|
21017
|
+
}
|
|
21018
|
+
}
|
|
21019
|
+
}
|
|
21020
|
+
/**
|
|
21021
|
+
* Merges another param map into this one.
|
|
21022
|
+
*/
|
|
21023
|
+
merge(other) {
|
|
21024
|
+
for (const [placeholder, otherValues] of other.values) {
|
|
21025
|
+
const currentValues = this.values.get(placeholder) || [];
|
|
21026
|
+
// Child element close tag params should be prepended to maintain the same order as
|
|
21027
|
+
// TemplateDefinitionBuilder.
|
|
21028
|
+
const flags = otherValues[0].flags;
|
|
21029
|
+
if ((flags & I18nParamValueFlags.CloseTag) && !(flags & I18nParamValueFlags.OpenTag)) {
|
|
21030
|
+
this.values.set(placeholder, [...otherValues, ...currentValues]);
|
|
21031
|
+
}
|
|
21032
|
+
else {
|
|
21033
|
+
this.values.set(placeholder, [...currentValues, ...otherValues]);
|
|
21034
|
+
}
|
|
20922
21035
|
}
|
|
20923
21036
|
}
|
|
20924
21037
|
/**
|
|
20925
21038
|
* Serializes a list of i18n placeholder values.
|
|
20926
21039
|
*/
|
|
20927
21040
|
serializeValues(values) {
|
|
21041
|
+
if (values.length === 0) {
|
|
21042
|
+
return null;
|
|
21043
|
+
}
|
|
20928
21044
|
const serializedValues = values.map(value => this.serializeValue(value));
|
|
20929
21045
|
return serializedValues.length === 1 ?
|
|
20930
21046
|
serializedValues[0] :
|
|
@@ -20946,6 +21062,11 @@ class I18nPlaceholderParams {
|
|
|
20946
21062
|
closeMarker = value.flags & I18nParamValueFlags.CloseTag ? TAG_CLOSE_MARKER : '';
|
|
20947
21063
|
}
|
|
20948
21064
|
const context = value.subTemplateIndex === null ? '' : `${CONTEXT_MARKER}${value.subTemplateIndex}`;
|
|
21065
|
+
// Self-closing tags use a special form that concatenates the start and close tag values.
|
|
21066
|
+
if ((value.flags & I18nParamValueFlags.OpenTag) &&
|
|
21067
|
+
(value.flags & I18nParamValueFlags.CloseTag)) {
|
|
21068
|
+
return `${ESCAPE}${tagMarker}${value.value}${context}${ESCAPE}${ESCAPE}${closeMarker}${tagMarker}${value.value}${context}${ESCAPE}`;
|
|
21069
|
+
}
|
|
20949
21070
|
return `${ESCAPE}${closeMarker}${tagMarker}${value.value}${context}${ESCAPE}`;
|
|
20950
21071
|
}
|
|
20951
21072
|
}
|
|
@@ -20953,36 +21074,81 @@ class I18nPlaceholderParams {
|
|
|
20953
21074
|
* Resolve the placeholders in i18n messages.
|
|
20954
21075
|
*/
|
|
20955
21076
|
function phaseResolveI18nPlaceholders(job) {
|
|
21077
|
+
const params = new Map();
|
|
21078
|
+
const i18nOps = new Map();
|
|
21079
|
+
resolvePlaceholders(job, params, i18nOps);
|
|
21080
|
+
propagatePlaceholders(params, i18nOps);
|
|
21081
|
+
// After colleccting all params, save them to the i18n ops.
|
|
21082
|
+
for (const [xref, i18nOpParams] of params) {
|
|
21083
|
+
i18nOpParams.saveToOp(i18nOps.get(xref));
|
|
21084
|
+
}
|
|
21085
|
+
// Validate the root i18n ops have all placeholders filled in.
|
|
21086
|
+
for (const op of i18nOps.values()) {
|
|
21087
|
+
if (op.xref === op.root) {
|
|
21088
|
+
for (const placeholder in op.message.placeholders) {
|
|
21089
|
+
if (!op.params.has(placeholder) && !op.postprocessingParams.has(placeholder)) {
|
|
21090
|
+
throw Error(`Failed to resolve i18n placeholder: ${placeholder}`);
|
|
21091
|
+
}
|
|
21092
|
+
}
|
|
21093
|
+
}
|
|
21094
|
+
}
|
|
21095
|
+
}
|
|
21096
|
+
/**
|
|
21097
|
+
* Resolve placeholders for each i18n op.
|
|
21098
|
+
*/
|
|
21099
|
+
function resolvePlaceholders(job, params, i18nOps) {
|
|
20956
21100
|
for (const unit of job.units) {
|
|
20957
|
-
const
|
|
20958
|
-
const params = new Map();
|
|
21101
|
+
const elements = new Map();
|
|
20959
21102
|
let currentI18nOp = null;
|
|
20960
21103
|
// Record slots for tag name placeholders.
|
|
20961
21104
|
for (const op of unit.create) {
|
|
20962
21105
|
switch (op.kind) {
|
|
20963
21106
|
case OpKind.I18nStart:
|
|
20964
|
-
case OpKind.I18n:
|
|
20965
21107
|
i18nOps.set(op.xref, op);
|
|
20966
21108
|
currentI18nOp = op.kind === OpKind.I18nStart ? op : null;
|
|
20967
21109
|
break;
|
|
20968
21110
|
case OpKind.I18nEnd:
|
|
20969
21111
|
currentI18nOp = null;
|
|
20970
21112
|
break;
|
|
20971
|
-
case OpKind.Element:
|
|
20972
21113
|
case OpKind.ElementStart:
|
|
20973
|
-
|
|
20974
|
-
//
|
|
20975
|
-
// the start and close placeholders.
|
|
21114
|
+
// For elements with i18n placeholders, record its slot value in the params map under the
|
|
21115
|
+
// corresponding tag start placeholder.
|
|
20976
21116
|
if (op.i18nPlaceholder !== undefined) {
|
|
20977
21117
|
if (currentI18nOp === null) {
|
|
20978
21118
|
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
20979
21119
|
}
|
|
21120
|
+
elements.set(op.xref, op);
|
|
20980
21121
|
const { startName, closeName } = op.i18nPlaceholder;
|
|
20981
|
-
|
|
20982
|
-
|
|
20983
|
-
|
|
20984
|
-
|
|
20985
|
-
|
|
21122
|
+
let flags = I18nParamValueFlags.ElementTag | I18nParamValueFlags.OpenTag;
|
|
21123
|
+
// For self-closing tags, there is no close tag placeholder. Instead, the start tag
|
|
21124
|
+
// placeholder accounts for the start and close of the element.
|
|
21125
|
+
if (closeName === '') {
|
|
21126
|
+
flags |= I18nParamValueFlags.CloseTag;
|
|
21127
|
+
}
|
|
21128
|
+
addParam(params, currentI18nOp, startName, op.slot, currentI18nOp.subTemplateIndex, I18nParamResolutionTime.Creation, flags);
|
|
21129
|
+
}
|
|
21130
|
+
break;
|
|
21131
|
+
case OpKind.ElementEnd:
|
|
21132
|
+
const startOp = elements.get(op.xref);
|
|
21133
|
+
if (startOp && startOp.i18nPlaceholder !== undefined) {
|
|
21134
|
+
if (currentI18nOp === null) {
|
|
21135
|
+
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
21136
|
+
}
|
|
21137
|
+
const { closeName } = startOp.i18nPlaceholder;
|
|
21138
|
+
// Self-closing tags don't have a closing tag placeholder.
|
|
21139
|
+
if (closeName !== '') {
|
|
21140
|
+
addParam(params, currentI18nOp, closeName, startOp.slot, currentI18nOp.subTemplateIndex, I18nParamResolutionTime.Creation, I18nParamValueFlags.ElementTag | I18nParamValueFlags.CloseTag);
|
|
21141
|
+
}
|
|
21142
|
+
}
|
|
21143
|
+
break;
|
|
21144
|
+
case OpKind.Template:
|
|
21145
|
+
if (op.i18nPlaceholder !== undefined) {
|
|
21146
|
+
if (currentI18nOp === null) {
|
|
21147
|
+
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
21148
|
+
}
|
|
21149
|
+
const subTemplateIndex = getSubTemplateIndexForTemplateTag(job, currentI18nOp, op);
|
|
21150
|
+
addParam(params, currentI18nOp, op.i18nPlaceholder.startName, op.slot, subTemplateIndex, I18nParamResolutionTime.Creation, I18nParamValueFlags.TemplateTag);
|
|
21151
|
+
addParam(params, currentI18nOp, op.i18nPlaceholder.closeName, op.slot, subTemplateIndex, I18nParamResolutionTime.Creation, I18nParamValueFlags.TemplateTag | I18nParamValueFlags.CloseTag);
|
|
20986
21152
|
}
|
|
20987
21153
|
break;
|
|
20988
21154
|
}
|
|
@@ -20996,39 +21162,44 @@ function phaseResolveI18nPlaceholders(job) {
|
|
|
20996
21162
|
if (!i18nOp) {
|
|
20997
21163
|
throw Error('Cannot find corresponding i18nStart for i18nExpr');
|
|
20998
21164
|
}
|
|
20999
|
-
addParam(params, i18nOp, op.i18nPlaceholder
|
|
21165
|
+
addParam(params, i18nOp, op.i18nPlaceholder, index++, i18nOp.subTemplateIndex, op.resolutionTime);
|
|
21000
21166
|
i18nBlockPlaceholderIndices.set(op.owner, index);
|
|
21001
21167
|
}
|
|
21002
21168
|
}
|
|
21003
|
-
// After colleccting all params, save them to the i18n ops.
|
|
21004
|
-
for (const [xref, i18nOpParams] of params) {
|
|
21005
|
-
i18nOpParams.saveToOp(i18nOps.get(xref));
|
|
21006
|
-
}
|
|
21007
21169
|
}
|
|
21008
21170
|
}
|
|
21009
21171
|
/**
|
|
21010
21172
|
* Add a param to the params map for the given i18n op.
|
|
21011
21173
|
*/
|
|
21012
|
-
function addParam(params, i18nOp, placeholder, value, subTemplateIndex, flags = I18nParamValueFlags.None) {
|
|
21013
|
-
const i18nOpParams = params.get(i18nOp.xref)
|
|
21014
|
-
i18nOpParams.addValue(placeholder, value, subTemplateIndex, flags);
|
|
21174
|
+
function addParam(params, i18nOp, placeholder, value, subTemplateIndex, resolutionTime, flags = I18nParamValueFlags.None) {
|
|
21175
|
+
const i18nOpParams = params.get(i18nOp.xref) || new I18nPlaceholderParams();
|
|
21176
|
+
i18nOpParams.addValue(placeholder, value, subTemplateIndex, resolutionTime, flags);
|
|
21015
21177
|
params.set(i18nOp.xref, i18nOpParams);
|
|
21016
21178
|
}
|
|
21017
21179
|
/**
|
|
21018
|
-
* Get the subTemplateIndex for the given op. For template ops, use the subTemplateIndex of
|
|
21019
|
-
* child i18n block inside the template.
|
|
21020
|
-
* block the op belongs to.
|
|
21180
|
+
* Get the subTemplateIndex for the given template op. For template ops, use the subTemplateIndex of
|
|
21181
|
+
* the child i18n block inside the template.
|
|
21021
21182
|
*/
|
|
21022
|
-
function
|
|
21023
|
-
|
|
21024
|
-
|
|
21025
|
-
|
|
21026
|
-
return childOp.subTemplateIndex;
|
|
21027
|
-
}
|
|
21183
|
+
function getSubTemplateIndexForTemplateTag(job, i18nOp, op) {
|
|
21184
|
+
for (const childOp of job.views.get(op.xref).create) {
|
|
21185
|
+
if (childOp.kind === OpKind.I18nStart) {
|
|
21186
|
+
return childOp.subTemplateIndex;
|
|
21028
21187
|
}
|
|
21029
21188
|
}
|
|
21030
21189
|
return i18nOp.subTemplateIndex;
|
|
21031
21190
|
}
|
|
21191
|
+
/**
|
|
21192
|
+
* Propagate placeholders up to their root i18n op.
|
|
21193
|
+
*/
|
|
21194
|
+
function propagatePlaceholders(params, i18nOps) {
|
|
21195
|
+
for (const [xref, opParams] of params) {
|
|
21196
|
+
const op = i18nOps.get(xref);
|
|
21197
|
+
if (op.xref !== op.root) {
|
|
21198
|
+
const rootParams = params.get(op.root) || new I18nPlaceholderParams();
|
|
21199
|
+
rootParams.merge(opParams);
|
|
21200
|
+
}
|
|
21201
|
+
}
|
|
21202
|
+
}
|
|
21032
21203
|
|
|
21033
21204
|
/**
|
|
21034
21205
|
* Resolves lexical references in views (`ir.LexicalReadExpr`) to either a target variable or to
|
|
@@ -21170,8 +21341,7 @@ function phaseResolveSanitizers(job) {
|
|
|
21170
21341
|
* Checks whether the given op represents an iframe element.
|
|
21171
21342
|
*/
|
|
21172
21343
|
function isIframeElement$1(op) {
|
|
21173
|
-
return
|
|
21174
|
-
op.tag.toLowerCase() === 'iframe';
|
|
21344
|
+
return op.kind === OpKind.ElementStart && op.tag?.toLowerCase() === 'iframe';
|
|
21175
21345
|
}
|
|
21176
21346
|
|
|
21177
21347
|
function phaseSaveRestoreView(job) {
|
|
@@ -21785,6 +21955,32 @@ function allowConservativeInlining(decl, target) {
|
|
|
21785
21955
|
}
|
|
21786
21956
|
}
|
|
21787
21957
|
|
|
21958
|
+
/**
|
|
21959
|
+
* Wraps ICUs that do not already belong to an i18n block in a new i18n block.
|
|
21960
|
+
*/
|
|
21961
|
+
function phaseWrapIcus(job) {
|
|
21962
|
+
for (const unit of job.units) {
|
|
21963
|
+
let currentI18nOp = null;
|
|
21964
|
+
for (const op of unit.create) {
|
|
21965
|
+
switch (op.kind) {
|
|
21966
|
+
case OpKind.I18nStart:
|
|
21967
|
+
currentI18nOp = op;
|
|
21968
|
+
break;
|
|
21969
|
+
case OpKind.I18nEnd:
|
|
21970
|
+
currentI18nOp = null;
|
|
21971
|
+
break;
|
|
21972
|
+
case OpKind.Icu:
|
|
21973
|
+
if (currentI18nOp === null) {
|
|
21974
|
+
const id = job.allocateXrefId();
|
|
21975
|
+
OpList.insertBefore(createI18nStartOp(id, op.message), op);
|
|
21976
|
+
OpList.insertAfter(createI18nEndOp(id), op);
|
|
21977
|
+
}
|
|
21978
|
+
break;
|
|
21979
|
+
}
|
|
21980
|
+
}
|
|
21981
|
+
}
|
|
21982
|
+
}
|
|
21983
|
+
|
|
21788
21984
|
const phases = [
|
|
21789
21985
|
{ kind: CompilationJobKind.Tmpl, fn: phaseRemoveContentSelectors },
|
|
21790
21986
|
{ kind: CompilationJobKind.Host, fn: phaseHostStylePropertyParsing },
|
|
@@ -21792,12 +21988,14 @@ const phases = [
|
|
|
21792
21988
|
{ kind: CompilationJobKind.Both, fn: phaseStyleBindingSpecialization },
|
|
21793
21989
|
{ kind: CompilationJobKind.Both, fn: phaseBindingSpecialization },
|
|
21794
21990
|
{ kind: CompilationJobKind.Tmpl, fn: phasePropagateI18nBlocks },
|
|
21991
|
+
{ kind: CompilationJobKind.Tmpl, fn: phaseWrapIcus },
|
|
21795
21992
|
{ kind: CompilationJobKind.Both, fn: phaseAttributeExtraction },
|
|
21796
21993
|
{ kind: CompilationJobKind.Both, fn: phaseParseExtractedStyles },
|
|
21797
21994
|
{ kind: CompilationJobKind.Tmpl, fn: phaseRemoveEmptyBindings },
|
|
21798
21995
|
{ kind: CompilationJobKind.Tmpl, fn: phaseConditionals },
|
|
21799
21996
|
{ kind: CompilationJobKind.Tmpl, fn: phasePipeCreation },
|
|
21800
21997
|
{ kind: CompilationJobKind.Tmpl, fn: phaseI18nTextExtraction },
|
|
21998
|
+
{ kind: CompilationJobKind.Tmpl, fn: phaseIcuExtraction },
|
|
21801
21999
|
{ kind: CompilationJobKind.Tmpl, fn: phaseApplyI18nExpressions },
|
|
21802
22000
|
{ kind: CompilationJobKind.Tmpl, fn: phasePipeVariadic },
|
|
21803
22001
|
{ kind: CompilationJobKind.Both, fn: phasePureLiteralStructures },
|
|
@@ -21815,7 +22013,6 @@ const phases = [
|
|
|
21815
22013
|
{ kind: CompilationJobKind.Both, fn: phaseTemporaryVariables },
|
|
21816
22014
|
{ kind: CompilationJobKind.Tmpl, fn: phaseSlotAllocation },
|
|
21817
22015
|
{ kind: CompilationJobKind.Tmpl, fn: phaseResolveI18nPlaceholders },
|
|
21818
|
-
{ kind: CompilationJobKind.Tmpl, fn: phasePropagateI18nPlaceholders },
|
|
21819
22016
|
{ kind: CompilationJobKind.Tmpl, fn: phaseI18nMessageExtraction },
|
|
21820
22017
|
{ kind: CompilationJobKind.Tmpl, fn: phaseI18nConstCollection },
|
|
21821
22018
|
{ kind: CompilationJobKind.Tmpl, fn: phaseConstTraitCollection },
|
|
@@ -22033,6 +22230,9 @@ function ingestNodes(unit, template) {
|
|
|
22033
22230
|
else if (node instanceof DeferredBlock) {
|
|
22034
22231
|
ingestDeferBlock(unit, node);
|
|
22035
22232
|
}
|
|
22233
|
+
else if (node instanceof Icu$1) {
|
|
22234
|
+
ingestIcu(unit, node);
|
|
22235
|
+
}
|
|
22036
22236
|
else {
|
|
22037
22237
|
throw new Error(`Unsupported template node: ${node.constructor.name}`);
|
|
22038
22238
|
}
|
|
@@ -22081,8 +22281,7 @@ function ingestTemplate(unit, tmpl) {
|
|
|
22081
22281
|
[namespacePrefix, tagNameWithoutNamespace] = splitNsName(tmpl.tagName);
|
|
22082
22282
|
}
|
|
22083
22283
|
const i18nPlaceholder = tmpl.i18n instanceof TagPlaceholder ? tmpl.i18n : undefined;
|
|
22084
|
-
|
|
22085
|
-
const tplOp = createTemplateOp(childView.xref, tagNameWithoutNamespace ?? 'ng-template', namespaceForKey(namespacePrefix), false, i18nPlaceholder, tmpl.startSourceSpan);
|
|
22284
|
+
const tplOp = createTemplateOp(childView.xref, tagNameWithoutNamespace, namespaceForKey(namespacePrefix), false, i18nPlaceholder, tmpl.startSourceSpan);
|
|
22086
22285
|
unit.create.push(tplOp);
|
|
22087
22286
|
ingestBindings(unit, tplOp, tmpl);
|
|
22088
22287
|
ingestReferences(tplOp, tmpl);
|
|
@@ -22090,8 +22289,10 @@ function ingestTemplate(unit, tmpl) {
|
|
|
22090
22289
|
for (const { name, value } of tmpl.variables) {
|
|
22091
22290
|
childView.contextVariables.set(name, value);
|
|
22092
22291
|
}
|
|
22093
|
-
// If there is an i18n message associated with
|
|
22094
|
-
|
|
22292
|
+
// If this is a plain template and there is an i18n message associated with it, insert i18n start
|
|
22293
|
+
// and end ops. For structural directive templates, the i18n ops will be added when ingesting the
|
|
22294
|
+
// element/template the directive is placed on.
|
|
22295
|
+
if (isPlainTemplate(tmpl) && tmpl.i18n instanceof Message) {
|
|
22095
22296
|
const id = unit.job.allocateXrefId();
|
|
22096
22297
|
OpList.insertAfter(createI18nStartOp(id, tmpl.i18n), childView.create.head);
|
|
22097
22298
|
OpList.insertBefore(createI18nEndOp(id), childView.create.tail);
|
|
@@ -22227,6 +22428,16 @@ function ingestDeferBlock(unit, deferBlock) {
|
|
|
22227
22428
|
// Add all ops to the view.
|
|
22228
22429
|
unit.create.push(deferOnOp);
|
|
22229
22430
|
}
|
|
22431
|
+
function ingestIcu(unit, icu) {
|
|
22432
|
+
if (icu.i18n instanceof Message) {
|
|
22433
|
+
const xref = unit.job.allocateXrefId();
|
|
22434
|
+
unit.create.push(createIcuOp(xref, icu.i18n, null));
|
|
22435
|
+
unit.update.push(createIcuUpdateOp(xref, null));
|
|
22436
|
+
}
|
|
22437
|
+
else {
|
|
22438
|
+
throw Error(`Unhandled i18n metadata type for ICU: ${icu.i18n?.constructor.name}`);
|
|
22439
|
+
}
|
|
22440
|
+
}
|
|
22230
22441
|
/**
|
|
22231
22442
|
* Convert a template AST expression into an output AST expression.
|
|
22232
22443
|
*/
|
|
@@ -22320,16 +22531,35 @@ function convertAst(ast, job, baseSourceSpan) {
|
|
|
22320
22531
|
throw new Error(`Unhandled expression type: ${ast.constructor.name}`);
|
|
22321
22532
|
}
|
|
22322
22533
|
}
|
|
22534
|
+
/**
|
|
22535
|
+
* Checks whether the given template is a plain ng-template (as opposed to another kind of template
|
|
22536
|
+
* such as a structural directive template or control flow template). This is checked based on the
|
|
22537
|
+
* tagName. We can expect that only plain ng-templates will come through with a tagName of
|
|
22538
|
+
* 'ng-template'.
|
|
22539
|
+
*
|
|
22540
|
+
* Here are some of the cases we expect:
|
|
22541
|
+
*
|
|
22542
|
+
* | Angular HTML | Template tagName |
|
|
22543
|
+
* | ---------------------------------- | ------------------ |
|
|
22544
|
+
* | `<ng-template>` | 'ng-template' |
|
|
22545
|
+
* | `<div *ngIf="true">` | 'div' |
|
|
22546
|
+
* | `<svg><ng-template>` | 'svg:ng-template' |
|
|
22547
|
+
* | `@if (true) {` | 'Conditional' |
|
|
22548
|
+
* | `<ng-template *ngIf>` (plain) | 'ng-template' |
|
|
22549
|
+
* | `<ng-template *ngIf>` (structural) | null |
|
|
22550
|
+
*/
|
|
22551
|
+
function isPlainTemplate(tmpl) {
|
|
22552
|
+
return splitNsName(tmpl.tagName ?? '')[1] === 'ng-template';
|
|
22553
|
+
}
|
|
22323
22554
|
/**
|
|
22324
22555
|
* Process all of the bindings on an element-like structure in the template AST and convert them
|
|
22325
22556
|
* to their IR representation.
|
|
22326
22557
|
*/
|
|
22327
22558
|
function ingestBindings(unit, op, element) {
|
|
22328
22559
|
let flags = BindingFlags.None;
|
|
22329
|
-
const isPlainTemplate = element instanceof Template && splitNsName(element.tagName ?? '')[1] === 'ng-template';
|
|
22330
22560
|
if (element instanceof Template) {
|
|
22331
22561
|
flags |= BindingFlags.OnNgTemplateElement;
|
|
22332
|
-
if (isPlainTemplate) {
|
|
22562
|
+
if (element instanceof Template && isPlainTemplate(element)) {
|
|
22333
22563
|
flags |= BindingFlags.BindingTargetsTemplate;
|
|
22334
22564
|
}
|
|
22335
22565
|
const templateAttrFlags = flags | BindingFlags.BindingTargetsTemplate | BindingFlags.IsStructuralTemplateAttribute;
|
|
@@ -22358,7 +22588,7 @@ function ingestBindings(unit, op, element) {
|
|
|
22358
22588
|
throw Error('Animation listener should have a phase');
|
|
22359
22589
|
}
|
|
22360
22590
|
}
|
|
22361
|
-
if (element instanceof Template && !isPlainTemplate) {
|
|
22591
|
+
if (element instanceof Template && !isPlainTemplate(element)) {
|
|
22362
22592
|
unit.create.push(createExtractedAttributeOp(op.xref, BindingKind.Property, output.name, null));
|
|
22363
22593
|
continue;
|
|
22364
22594
|
}
|
|
@@ -29526,7 +29756,7 @@ function publishFacade(global) {
|
|
|
29526
29756
|
* @description
|
|
29527
29757
|
* Entry point for all public APIs of the compiler package.
|
|
29528
29758
|
*/
|
|
29529
|
-
const VERSION = new Version('17.0.0-
|
|
29759
|
+
const VERSION = new Version('17.0.0-rc.0');
|
|
29530
29760
|
|
|
29531
29761
|
class CompilerConfig {
|
|
29532
29762
|
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
@@ -31056,7 +31286,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
|
|
|
31056
31286
|
function compileDeclareClassMetadata(metadata) {
|
|
31057
31287
|
const definitionMap = new DefinitionMap();
|
|
31058
31288
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
31059
|
-
definitionMap.set('version', literal('17.0.0-
|
|
31289
|
+
definitionMap.set('version', literal('17.0.0-rc.0'));
|
|
31060
31290
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
31061
31291
|
definitionMap.set('type', metadata.type);
|
|
31062
31292
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -31164,7 +31394,7 @@ function createDirectiveDefinitionMap(meta) {
|
|
|
31164
31394
|
// in 16.1 is actually used.
|
|
31165
31395
|
const minVersion = hasTransformFunctions ? MINIMUM_PARTIAL_LINKER_VERSION$5 : '14.0.0';
|
|
31166
31396
|
definitionMap.set('minVersion', literal(minVersion));
|
|
31167
|
-
definitionMap.set('version', literal('17.0.0-
|
|
31397
|
+
definitionMap.set('version', literal('17.0.0-rc.0'));
|
|
31168
31398
|
// e.g. `type: MyDirective`
|
|
31169
31399
|
definitionMap.set('type', meta.type.value);
|
|
31170
31400
|
if (meta.isStandalone) {
|
|
@@ -31441,7 +31671,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
31441
31671
|
function compileDeclareFactoryFunction(meta) {
|
|
31442
31672
|
const definitionMap = new DefinitionMap();
|
|
31443
31673
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
31444
|
-
definitionMap.set('version', literal('17.0.0-
|
|
31674
|
+
definitionMap.set('version', literal('17.0.0-rc.0'));
|
|
31445
31675
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
31446
31676
|
definitionMap.set('type', meta.type.value);
|
|
31447
31677
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -31476,7 +31706,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
31476
31706
|
function createInjectableDefinitionMap(meta) {
|
|
31477
31707
|
const definitionMap = new DefinitionMap();
|
|
31478
31708
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
31479
|
-
definitionMap.set('version', literal('17.0.0-
|
|
31709
|
+
definitionMap.set('version', literal('17.0.0-rc.0'));
|
|
31480
31710
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
31481
31711
|
definitionMap.set('type', meta.type.value);
|
|
31482
31712
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -31527,7 +31757,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
31527
31757
|
function createInjectorDefinitionMap(meta) {
|
|
31528
31758
|
const definitionMap = new DefinitionMap();
|
|
31529
31759
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
31530
|
-
definitionMap.set('version', literal('17.0.0-
|
|
31760
|
+
definitionMap.set('version', literal('17.0.0-rc.0'));
|
|
31531
31761
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
31532
31762
|
definitionMap.set('type', meta.type.value);
|
|
31533
31763
|
definitionMap.set('providers', meta.providers);
|
|
@@ -31560,7 +31790,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
31560
31790
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
31561
31791
|
}
|
|
31562
31792
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
31563
|
-
definitionMap.set('version', literal('17.0.0-
|
|
31793
|
+
definitionMap.set('version', literal('17.0.0-rc.0'));
|
|
31564
31794
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
31565
31795
|
definitionMap.set('type', meta.type.value);
|
|
31566
31796
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -31611,7 +31841,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
31611
31841
|
function createPipeDefinitionMap(meta) {
|
|
31612
31842
|
const definitionMap = new DefinitionMap();
|
|
31613
31843
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
31614
|
-
definitionMap.set('version', literal('17.0.0-
|
|
31844
|
+
definitionMap.set('version', literal('17.0.0-rc.0'));
|
|
31615
31845
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
31616
31846
|
// e.g. `type: MyPipe`
|
|
31617
31847
|
definitionMap.set('type', meta.type.value);
|