@angular/compiler 17.1.0-next.3 → 17.1.0-next.4
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 -2
- package/esm2022/src/compiler_facade_interface.mjs +1 -1
- package/esm2022/src/jit_compiler_facade.mjs +46 -17
- package/esm2022/src/render3/partial/api.mjs +1 -1
- package/esm2022/src/render3/partial/class_metadata.mjs +1 -1
- package/esm2022/src/render3/partial/directive.mjs +112 -17
- package/esm2022/src/render3/partial/factory.mjs +1 -1
- package/esm2022/src/render3/partial/injectable.mjs +1 -1
- package/esm2022/src/render3/partial/injector.mjs +1 -1
- package/esm2022/src/render3/partial/ng_module.mjs +1 -1
- package/esm2022/src/render3/partial/pipe.mjs +1 -1
- package/esm2022/src/render3/r3_identifiers.mjs +4 -1
- package/esm2022/src/render3/view/api.mjs +1 -1
- package/esm2022/src/render3/view/compiler.mjs +24 -9
- package/esm2022/src/render3/view/util.mjs +8 -2
- package/esm2022/src/template/pipeline/ir/src/enums.mjs +9 -17
- package/esm2022/src/template/pipeline/ir/src/expression.mjs +12 -20
- package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +14 -6
- package/esm2022/src/template/pipeline/ir/src/ops/host.mjs +4 -2
- package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +15 -9
- package/esm2022/src/template/pipeline/src/emit.mjs +4 -4
- package/esm2022/src/template/pipeline/src/ingest.mjs +240 -155
- package/esm2022/src/template/pipeline/src/instruction.mjs +14 -14
- package/esm2022/src/template/pipeline/src/phases/assign_i18n_slot_dependencies.mjs +40 -56
- package/esm2022/src/template/pipeline/src/phases/attribute_extraction.mjs +15 -8
- package/esm2022/src/template/pipeline/src/phases/binding_specialization.mjs +4 -4
- package/esm2022/src/template/pipeline/src/phases/const_collection.mjs +13 -4
- package/esm2022/src/template/pipeline/src/phases/create_i18n_contexts.mjs +23 -1
- package/esm2022/src/template/pipeline/src/phases/generate_variables.mjs +7 -1
- package/esm2022/src/template/pipeline/src/phases/i18n_const_collection.mjs +10 -6
- package/esm2022/src/template/pipeline/src/phases/parse_extracted_styles.mjs +4 -3
- package/esm2022/src/template/pipeline/src/phases/propagate_i18n_blocks.mjs +27 -12
- package/esm2022/src/template/pipeline/src/phases/reify.mjs +12 -15
- package/esm2022/src/template/pipeline/src/phases/resolve_i18n_element_placeholders.mjs +60 -14
- package/esm2022/src/template/pipeline/src/phases/resolve_sanitizers.mjs +78 -14
- package/esm2022/src/template/pipeline/src/phases/slot_allocation.mjs +3 -1
- package/esm2022/src/template/pipeline/src/phases/var_counting.mjs +3 -1
- package/esm2022/src/version.mjs +1 -1
- package/fesm2022/compiler.mjs +778 -392
- package/fesm2022/compiler.mjs.map +1 -1
- package/index.d.ts +39 -6
- package/package.json +2 -2
package/fesm2022/compiler.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v17.1.0-next.
|
|
2
|
+
* @license Angular v17.1.0-next.4
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -2636,6 +2636,9 @@ class Identifiers {
|
|
|
2636
2636
|
static { this.trustConstantHtml = { name: 'ɵɵtrustConstantHtml', moduleName: CORE }; }
|
|
2637
2637
|
static { this.trustConstantResourceUrl = { name: 'ɵɵtrustConstantResourceUrl', moduleName: CORE }; }
|
|
2638
2638
|
static { this.validateIframeAttribute = { name: 'ɵɵvalidateIframeAttribute', moduleName: CORE }; }
|
|
2639
|
+
// type-checking
|
|
2640
|
+
static { this.InputSignalBrandWriteType = { name: 'ɵINPUT_SIGNAL_BRAND_WRITE_TYPE', moduleName: CORE }; }
|
|
2641
|
+
static { this.UnwrapDirectiveSignalInputs = { name: 'ɵUnwrapDirectiveSignalInputs', moduleName: CORE }; }
|
|
2639
2642
|
}
|
|
2640
2643
|
|
|
2641
2644
|
const DASH_CASE_REGEXP = /-+([a-z0-9])/g;
|
|
@@ -4957,6 +4960,12 @@ function asLiteral(value) {
|
|
|
4957
4960
|
}
|
|
4958
4961
|
return literal(value, INFERRED_TYPE);
|
|
4959
4962
|
}
|
|
4963
|
+
/**
|
|
4964
|
+
* Serializes inputs and outputs for `defineDirective` and `defineComponent`.
|
|
4965
|
+
*
|
|
4966
|
+
* This will attempt to generate optimized data structures to minimize memory or
|
|
4967
|
+
* file size of fully compiled applications.
|
|
4968
|
+
*/
|
|
4960
4969
|
function conditionallyCreateDirectiveBindingLiteral(map, keepDeclared) {
|
|
4961
4970
|
const keys = Object.getOwnPropertyNames(map);
|
|
4962
4971
|
if (keys.length === 0) {
|
|
@@ -9064,23 +9073,27 @@ var ExpressionKind;
|
|
|
9064
9073
|
* An expression representing a sanitizer function.
|
|
9065
9074
|
*/
|
|
9066
9075
|
ExpressionKind[ExpressionKind["SanitizerExpr"] = 20] = "SanitizerExpr";
|
|
9076
|
+
/**
|
|
9077
|
+
* An expression representing a function to create trusted values.
|
|
9078
|
+
*/
|
|
9079
|
+
ExpressionKind[ExpressionKind["TrustedValueFnExpr"] = 21] = "TrustedValueFnExpr";
|
|
9067
9080
|
/**
|
|
9068
9081
|
* An expression that will cause a literal slot index to be emitted.
|
|
9069
9082
|
*/
|
|
9070
|
-
ExpressionKind[ExpressionKind["SlotLiteralExpr"] =
|
|
9083
|
+
ExpressionKind[ExpressionKind["SlotLiteralExpr"] = 22] = "SlotLiteralExpr";
|
|
9071
9084
|
/**
|
|
9072
9085
|
* A test expression for a conditional op.
|
|
9073
9086
|
*/
|
|
9074
|
-
ExpressionKind[ExpressionKind["ConditionalCase"] =
|
|
9087
|
+
ExpressionKind[ExpressionKind["ConditionalCase"] = 23] = "ConditionalCase";
|
|
9075
9088
|
/**
|
|
9076
9089
|
* A variable for use inside a repeater, providing one of the ambiently-available context
|
|
9077
9090
|
* properties ($even, $first, etc.).
|
|
9078
9091
|
*/
|
|
9079
|
-
ExpressionKind[ExpressionKind["DerivedRepeaterVar"] =
|
|
9092
|
+
ExpressionKind[ExpressionKind["DerivedRepeaterVar"] = 24] = "DerivedRepeaterVar";
|
|
9080
9093
|
/**
|
|
9081
9094
|
* An expression that will be automatically extracted to the component const array.
|
|
9082
9095
|
*/
|
|
9083
|
-
ExpressionKind[ExpressionKind["ConstCollected"] =
|
|
9096
|
+
ExpressionKind[ExpressionKind["ConstCollected"] = 25] = "ConstCollected";
|
|
9084
9097
|
})(ExpressionKind || (ExpressionKind = {}));
|
|
9085
9098
|
var VariableFlags;
|
|
9086
9099
|
(function (VariableFlags) {
|
|
@@ -9124,18 +9137,6 @@ var CompatibilityMode;
|
|
|
9124
9137
|
CompatibilityMode[CompatibilityMode["Normal"] = 0] = "Normal";
|
|
9125
9138
|
CompatibilityMode[CompatibilityMode["TemplateDefinitionBuilder"] = 1] = "TemplateDefinitionBuilder";
|
|
9126
9139
|
})(CompatibilityMode || (CompatibilityMode = {}));
|
|
9127
|
-
/**
|
|
9128
|
-
* Represents functions used to sanitize different pieces of a template.
|
|
9129
|
-
*/
|
|
9130
|
-
var SanitizerFn;
|
|
9131
|
-
(function (SanitizerFn) {
|
|
9132
|
-
SanitizerFn[SanitizerFn["Html"] = 0] = "Html";
|
|
9133
|
-
SanitizerFn[SanitizerFn["Script"] = 1] = "Script";
|
|
9134
|
-
SanitizerFn[SanitizerFn["Style"] = 2] = "Style";
|
|
9135
|
-
SanitizerFn[SanitizerFn["Url"] = 3] = "Url";
|
|
9136
|
-
SanitizerFn[SanitizerFn["ResourceUrl"] = 4] = "ResourceUrl";
|
|
9137
|
-
SanitizerFn[SanitizerFn["IframeAttribute"] = 5] = "IframeAttribute";
|
|
9138
|
-
})(SanitizerFn || (SanitizerFn = {}));
|
|
9139
9140
|
/**
|
|
9140
9141
|
* Enumeration of the different kinds of `@defer` secondary blocks.
|
|
9141
9142
|
*/
|
|
@@ -9414,7 +9415,7 @@ class Interpolation {
|
|
|
9414
9415
|
/**
|
|
9415
9416
|
* Create a `BindingOp`, not yet transformed into a particular type of binding.
|
|
9416
9417
|
*/
|
|
9417
|
-
function createBindingOp(target, kind, name, expression, unit, securityContext, isTextAttribute,
|
|
9418
|
+
function createBindingOp(target, kind, name, expression, unit, securityContext, isTextAttribute, isStructuralTemplateAttribute, templateKind, i18nMessage, sourceSpan) {
|
|
9418
9419
|
return {
|
|
9419
9420
|
kind: OpKind.Binding,
|
|
9420
9421
|
bindingKind: kind,
|
|
@@ -9424,8 +9425,10 @@ function createBindingOp(target, kind, name, expression, unit, securityContext,
|
|
|
9424
9425
|
unit,
|
|
9425
9426
|
securityContext,
|
|
9426
9427
|
isTextAttribute,
|
|
9427
|
-
|
|
9428
|
-
|
|
9428
|
+
isStructuralTemplateAttribute,
|
|
9429
|
+
templateKind,
|
|
9430
|
+
i18nContext: null,
|
|
9431
|
+
i18nMessage,
|
|
9429
9432
|
sourceSpan,
|
|
9430
9433
|
...NEW_OP,
|
|
9431
9434
|
};
|
|
@@ -9433,7 +9436,7 @@ function createBindingOp(target, kind, name, expression, unit, securityContext,
|
|
|
9433
9436
|
/**
|
|
9434
9437
|
* Create a `PropertyOp`.
|
|
9435
9438
|
*/
|
|
9436
|
-
function createPropertyOp(target, name, expression, isAnimationTrigger, securityContext,
|
|
9439
|
+
function createPropertyOp(target, name, expression, isAnimationTrigger, securityContext, isStructuralTemplateAttribute, templateKind, i18nContext, i18nMessage, sourceSpan) {
|
|
9437
9440
|
return {
|
|
9438
9441
|
kind: OpKind.Property,
|
|
9439
9442
|
target,
|
|
@@ -9442,8 +9445,10 @@ function createPropertyOp(target, name, expression, isAnimationTrigger, security
|
|
|
9442
9445
|
isAnimationTrigger,
|
|
9443
9446
|
securityContext,
|
|
9444
9447
|
sanitizer: null,
|
|
9445
|
-
|
|
9448
|
+
isStructuralTemplateAttribute,
|
|
9449
|
+
templateKind,
|
|
9446
9450
|
i18nContext,
|
|
9451
|
+
i18nMessage,
|
|
9447
9452
|
sourceSpan,
|
|
9448
9453
|
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9449
9454
|
...TRAIT_CONSUMES_VARS,
|
|
@@ -9508,7 +9513,7 @@ function createClassMapOp(xref, expression, sourceSpan) {
|
|
|
9508
9513
|
/**
|
|
9509
9514
|
* Create an `AttributeOp`.
|
|
9510
9515
|
*/
|
|
9511
|
-
function createAttributeOp(target, name, expression, securityContext, isTextAttribute,
|
|
9516
|
+
function createAttributeOp(target, name, expression, securityContext, isTextAttribute, isStructuralTemplateAttribute, templateKind, i18nMessage, sourceSpan) {
|
|
9512
9517
|
return {
|
|
9513
9518
|
kind: OpKind.Attribute,
|
|
9514
9519
|
target,
|
|
@@ -9517,8 +9522,10 @@ function createAttributeOp(target, name, expression, securityContext, isTextAttr
|
|
|
9517
9522
|
securityContext,
|
|
9518
9523
|
sanitizer: null,
|
|
9519
9524
|
isTextAttribute,
|
|
9520
|
-
|
|
9521
|
-
|
|
9525
|
+
isStructuralTemplateAttribute,
|
|
9526
|
+
templateKind,
|
|
9527
|
+
i18nContext: null,
|
|
9528
|
+
i18nMessage,
|
|
9522
9529
|
sourceSpan,
|
|
9523
9530
|
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9524
9531
|
...TRAIT_CONSUMES_VARS,
|
|
@@ -10152,24 +10159,6 @@ class ReadTemporaryExpr extends ExpressionBase {
|
|
|
10152
10159
|
return r;
|
|
10153
10160
|
}
|
|
10154
10161
|
}
|
|
10155
|
-
class SanitizerExpr extends ExpressionBase {
|
|
10156
|
-
constructor(fn) {
|
|
10157
|
-
super();
|
|
10158
|
-
this.fn = fn;
|
|
10159
|
-
this.kind = ExpressionKind.SanitizerExpr;
|
|
10160
|
-
}
|
|
10161
|
-
visitExpression(visitor, context) { }
|
|
10162
|
-
isEquivalent(e) {
|
|
10163
|
-
return e instanceof SanitizerExpr && e.fn === this.fn;
|
|
10164
|
-
}
|
|
10165
|
-
isConstant() {
|
|
10166
|
-
return true;
|
|
10167
|
-
}
|
|
10168
|
-
clone() {
|
|
10169
|
-
return new SanitizerExpr(this.fn);
|
|
10170
|
-
}
|
|
10171
|
-
transformInternalExpressions() { }
|
|
10172
|
-
}
|
|
10173
10162
|
class SlotLiteralExpr extends ExpressionBase {
|
|
10174
10163
|
constructor(slot) {
|
|
10175
10164
|
super();
|
|
@@ -10300,7 +10289,6 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
10300
10289
|
case OpKind.ClassProp:
|
|
10301
10290
|
case OpKind.ClassMap:
|
|
10302
10291
|
case OpKind.Binding:
|
|
10303
|
-
case OpKind.HostProperty:
|
|
10304
10292
|
if (op.expression instanceof Interpolation) {
|
|
10305
10293
|
transformExpressionsInInterpolation(op.expression, transform, flags);
|
|
10306
10294
|
}
|
|
@@ -10309,6 +10297,7 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
10309
10297
|
}
|
|
10310
10298
|
break;
|
|
10311
10299
|
case OpKind.Property:
|
|
10300
|
+
case OpKind.HostProperty:
|
|
10312
10301
|
case OpKind.Attribute:
|
|
10313
10302
|
if (op.expression instanceof Interpolation) {
|
|
10314
10303
|
transformExpressionsInInterpolation(op.expression, transform, flags);
|
|
@@ -10354,6 +10343,8 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
10354
10343
|
case OpKind.ExtractedAttribute:
|
|
10355
10344
|
op.expression =
|
|
10356
10345
|
op.expression && transformExpressionsInExpression(op.expression, transform, flags);
|
|
10346
|
+
op.trustedValueFn = op.trustedValueFn &&
|
|
10347
|
+
transformExpressionsInExpression(op.trustedValueFn, transform, flags);
|
|
10357
10348
|
break;
|
|
10358
10349
|
case OpKind.RepeaterCreate:
|
|
10359
10350
|
op.track = transformExpressionsInExpression(op.track, transform, flags);
|
|
@@ -10485,6 +10476,14 @@ function transformExpressionsInExpression(expr, transform, flags) {
|
|
|
10485
10476
|
else if (expr instanceof NotExpr) {
|
|
10486
10477
|
expr.condition = transformExpressionsInExpression(expr.condition, transform, flags);
|
|
10487
10478
|
}
|
|
10479
|
+
else if (expr instanceof TaggedTemplateExpr) {
|
|
10480
|
+
expr.tag = transformExpressionsInExpression(expr.tag, transform, flags);
|
|
10481
|
+
expr.template.expressions =
|
|
10482
|
+
expr.template.expressions.map(e => transformExpressionsInExpression(e, transform, flags));
|
|
10483
|
+
}
|
|
10484
|
+
else if (expr instanceof WrappedNodeExpr) {
|
|
10485
|
+
// TODO: Do we need to transform any TS nodes nested inside of this expression?
|
|
10486
|
+
}
|
|
10488
10487
|
else if (expr instanceof ReadVarExpr || expr instanceof ExternalExpr ||
|
|
10489
10488
|
expr instanceof LiteralExpr) {
|
|
10490
10489
|
// No action for these types.
|
|
@@ -10846,7 +10845,7 @@ function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace
|
|
|
10846
10845
|
...NEW_OP,
|
|
10847
10846
|
};
|
|
10848
10847
|
}
|
|
10849
|
-
function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, sourceSpan) {
|
|
10848
|
+
function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, i18nPlaceholder, emptyI18nPlaceholder, sourceSpan) {
|
|
10850
10849
|
return {
|
|
10851
10850
|
kind: OpKind.RepeaterCreate,
|
|
10852
10851
|
attributes: null,
|
|
@@ -10864,6 +10863,8 @@ function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, so
|
|
|
10864
10863
|
vars: null,
|
|
10865
10864
|
varNames,
|
|
10866
10865
|
usesComponentInstance: false,
|
|
10866
|
+
i18nPlaceholder,
|
|
10867
|
+
emptyI18nPlaceholder,
|
|
10867
10868
|
sourceSpan,
|
|
10868
10869
|
...TRAIT_CONSUMES_SLOT,
|
|
10869
10870
|
...NEW_OP,
|
|
@@ -10912,7 +10913,9 @@ function createTextOp(xref, initialValue, sourceSpan) {
|
|
|
10912
10913
|
/**
|
|
10913
10914
|
* Create a `ListenerOp`. Host bindings reuse all the listener logic.
|
|
10914
10915
|
*/
|
|
10915
|
-
function createListenerOp(target, targetSlot, name, tag, animationPhase, hostListener, sourceSpan) {
|
|
10916
|
+
function createListenerOp(target, targetSlot, name, tag, handlerOps, animationPhase, eventTarget, hostListener, sourceSpan) {
|
|
10917
|
+
const handlerList = new OpList();
|
|
10918
|
+
handlerList.push(handlerOps);
|
|
10916
10919
|
return {
|
|
10917
10920
|
kind: OpKind.Listener,
|
|
10918
10921
|
target,
|
|
@@ -10920,11 +10923,12 @@ function createListenerOp(target, targetSlot, name, tag, animationPhase, hostLis
|
|
|
10920
10923
|
tag,
|
|
10921
10924
|
hostListener,
|
|
10922
10925
|
name,
|
|
10923
|
-
handlerOps:
|
|
10926
|
+
handlerOps: handlerList,
|
|
10924
10927
|
handlerFnName: null,
|
|
10925
10928
|
consumesDollarEvent: false,
|
|
10926
10929
|
isAnimationListener: animationPhase !== null,
|
|
10927
|
-
animationPhase
|
|
10930
|
+
animationPhase,
|
|
10931
|
+
eventTarget,
|
|
10928
10932
|
sourceSpan,
|
|
10929
10933
|
...NEW_OP,
|
|
10930
10934
|
};
|
|
@@ -10971,7 +10975,7 @@ function createProjectionOp(xref, selector, i18nPlaceholder, attributes, sourceS
|
|
|
10971
10975
|
/**
|
|
10972
10976
|
* Create an `ExtractedAttributeOp`.
|
|
10973
10977
|
*/
|
|
10974
|
-
function createExtractedAttributeOp(target, bindingKind, name, expression, i18nContext) {
|
|
10978
|
+
function createExtractedAttributeOp(target, bindingKind, name, expression, i18nContext, i18nMessage, securityContext) {
|
|
10975
10979
|
return {
|
|
10976
10980
|
kind: OpKind.ExtractedAttribute,
|
|
10977
10981
|
target,
|
|
@@ -10979,6 +10983,9 @@ function createExtractedAttributeOp(target, bindingKind, name, expression, i18nC
|
|
|
10979
10983
|
name,
|
|
10980
10984
|
expression,
|
|
10981
10985
|
i18nContext,
|
|
10986
|
+
i18nMessage,
|
|
10987
|
+
securityContext,
|
|
10988
|
+
trustedValueFn: null,
|
|
10982
10989
|
...NEW_OP,
|
|
10983
10990
|
};
|
|
10984
10991
|
}
|
|
@@ -11121,13 +11128,15 @@ function literalOrArrayLiteral$1(value) {
|
|
|
11121
11128
|
return literal(value, INFERRED_TYPE);
|
|
11122
11129
|
}
|
|
11123
11130
|
|
|
11124
|
-
function createHostPropertyOp(name, expression, isAnimationTrigger, i18nContext, sourceSpan) {
|
|
11131
|
+
function createHostPropertyOp(name, expression, isAnimationTrigger, i18nContext, securityContext, sourceSpan) {
|
|
11125
11132
|
return {
|
|
11126
11133
|
kind: OpKind.HostProperty,
|
|
11127
11134
|
name,
|
|
11128
11135
|
expression,
|
|
11129
11136
|
isAnimationTrigger,
|
|
11130
11137
|
i18nContext,
|
|
11138
|
+
securityContext,
|
|
11139
|
+
sanitizer: null,
|
|
11131
11140
|
sourceSpan,
|
|
11132
11141
|
...TRAIT_CONSUMES_VARS,
|
|
11133
11142
|
...NEW_OP,
|
|
@@ -11407,68 +11416,52 @@ function needsApplication(i18nContexts, op) {
|
|
|
11407
11416
|
* after the last update instruction that depends on that slot.
|
|
11408
11417
|
*/
|
|
11409
11418
|
function assignI18nSlotDependencies(job) {
|
|
11410
|
-
const i18nLastSlotConsumers = new Map();
|
|
11411
|
-
let lastSlotConsumer = null;
|
|
11412
|
-
let currentI18nOp = null;
|
|
11413
11419
|
for (const unit of job.units) {
|
|
11414
|
-
//
|
|
11415
|
-
|
|
11416
|
-
|
|
11417
|
-
|
|
11420
|
+
// The first update op.
|
|
11421
|
+
let updateOp = unit.update.head;
|
|
11422
|
+
// I18n expressions currently being moved during the iteration.
|
|
11423
|
+
let i18nExpressionsInProgress = [];
|
|
11424
|
+
// Non-null while we are iterating through an i18nStart/i18nEnd pair
|
|
11425
|
+
let state = null;
|
|
11426
|
+
for (const createOp of unit.create) {
|
|
11427
|
+
if (createOp.kind === OpKind.I18nStart) {
|
|
11428
|
+
state = {
|
|
11429
|
+
blockXref: createOp.xref,
|
|
11430
|
+
lastSlotConsumer: createOp.xref,
|
|
11431
|
+
};
|
|
11418
11432
|
}
|
|
11419
|
-
|
|
11420
|
-
|
|
11421
|
-
|
|
11422
|
-
|
|
11423
|
-
|
|
11424
|
-
|
|
11425
|
-
|
|
11433
|
+
else if (createOp.kind === OpKind.I18nEnd) {
|
|
11434
|
+
for (const op of i18nExpressionsInProgress) {
|
|
11435
|
+
op.target = state.lastSlotConsumer;
|
|
11436
|
+
OpList.insertBefore(op, updateOp);
|
|
11437
|
+
}
|
|
11438
|
+
i18nExpressionsInProgress.length = 0;
|
|
11439
|
+
state = null;
|
|
11440
|
+
}
|
|
11441
|
+
if (hasConsumesSlotTrait(createOp)) {
|
|
11442
|
+
if (state !== null) {
|
|
11443
|
+
state.lastSlotConsumer = createOp.xref;
|
|
11444
|
+
}
|
|
11445
|
+
while (true) {
|
|
11446
|
+
if (updateOp.next === null) {
|
|
11447
|
+
break;
|
|
11426
11448
|
}
|
|
11427
|
-
if (
|
|
11428
|
-
|
|
11449
|
+
if (state !== null && updateOp.kind === OpKind.I18nExpression &&
|
|
11450
|
+
updateOp.usage === I18nExpressionFor.I18nText &&
|
|
11451
|
+
updateOp.i18nOwner === state.blockXref) {
|
|
11452
|
+
const opToRemove = updateOp;
|
|
11453
|
+
updateOp = updateOp.next;
|
|
11454
|
+
OpList.remove(opToRemove);
|
|
11455
|
+
i18nExpressionsInProgress.push(opToRemove);
|
|
11456
|
+
continue;
|
|
11429
11457
|
}
|
|
11430
|
-
|
|
11431
|
-
|
|
11432
|
-
|
|
11433
|
-
|
|
11434
|
-
}
|
|
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;
|
|
11445
|
-
for (const op of unit.update) {
|
|
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');
|
|
11458
|
+
if (hasDependsOnSlotContextTrait(updateOp) && updateOp.target !== createOp.xref) {
|
|
11459
|
+
break;
|
|
11460
|
+
}
|
|
11461
|
+
updateOp = updateOp.next;
|
|
11464
11462
|
}
|
|
11465
|
-
op.target = target;
|
|
11466
|
-
moveAfterTarget = op.target;
|
|
11467
11463
|
}
|
|
11468
11464
|
}
|
|
11469
|
-
if (moveAfterTarget !== null) {
|
|
11470
|
-
unit.update.push(opsToMove);
|
|
11471
|
-
}
|
|
11472
11465
|
}
|
|
11473
11466
|
}
|
|
11474
11467
|
|
|
@@ -11501,19 +11494,21 @@ function extractAttributes(job) {
|
|
|
11501
11494
|
case OpKind.Property:
|
|
11502
11495
|
if (!op.isAnimationTrigger) {
|
|
11503
11496
|
let bindingKind;
|
|
11504
|
-
if (op.
|
|
11497
|
+
if (op.i18nMessage !== null && op.templateKind === null) {
|
|
11505
11498
|
// If the binding has an i18n context, it is an i18n attribute, and should have that
|
|
11506
11499
|
// kind in the consts array.
|
|
11507
11500
|
bindingKind = BindingKind.I18n;
|
|
11508
11501
|
}
|
|
11509
|
-
else if (op.
|
|
11510
|
-
// TODO: How do i18n attributes on templates work?!
|
|
11502
|
+
else if (op.isStructuralTemplateAttribute) {
|
|
11511
11503
|
bindingKind = BindingKind.Template;
|
|
11512
11504
|
}
|
|
11513
11505
|
else {
|
|
11514
11506
|
bindingKind = BindingKind.Property;
|
|
11515
11507
|
}
|
|
11516
|
-
OpList.insertBefore(
|
|
11508
|
+
OpList.insertBefore(
|
|
11509
|
+
// Deliberaly null i18nMessage value
|
|
11510
|
+
createExtractedAttributeOp(op.target, bindingKind, op.name, /* expression */ null, /* i18nContext */ null,
|
|
11511
|
+
/* i18nMessage */ null, op.securityContext), lookupElement$2(elements, op.target));
|
|
11517
11512
|
}
|
|
11518
11513
|
break;
|
|
11519
11514
|
case OpKind.StyleProp:
|
|
@@ -11524,12 +11519,16 @@ function extractAttributes(job) {
|
|
|
11524
11519
|
// mode.
|
|
11525
11520
|
if (unit.job.compatibility === CompatibilityMode.TemplateDefinitionBuilder &&
|
|
11526
11521
|
op.expression instanceof EmptyExpr) {
|
|
11527
|
-
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.Property, op.name,
|
|
11522
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.Property, op.name, /* expression */ null,
|
|
11523
|
+
/* i18nContext */ null,
|
|
11524
|
+
/* i18nMessage */ null, SecurityContext.STYLE), lookupElement$2(elements, op.target));
|
|
11528
11525
|
}
|
|
11529
11526
|
break;
|
|
11530
11527
|
case OpKind.Listener:
|
|
11531
11528
|
if (!op.isAnimationListener) {
|
|
11532
|
-
const extractedAttributeOp = createExtractedAttributeOp(op.target, BindingKind.Property, op.name, null,
|
|
11529
|
+
const extractedAttributeOp = createExtractedAttributeOp(op.target, BindingKind.Property, op.name, /* expression */ null,
|
|
11530
|
+
/* i18nContext */ null,
|
|
11531
|
+
/* i18nMessage */ null, SecurityContext.NONE);
|
|
11533
11532
|
if (job.kind === CompilationJobKind.Host) {
|
|
11534
11533
|
// This attribute will apply to the enclosing host binding compilation unit, so order
|
|
11535
11534
|
// doesn't matter.
|
|
@@ -11578,7 +11577,7 @@ function extractAttributeOp(unit, op, elements) {
|
|
|
11578
11577
|
}
|
|
11579
11578
|
}
|
|
11580
11579
|
if (extractable) {
|
|
11581
|
-
const extractedAttributeOp = createExtractedAttributeOp(op.target, op.
|
|
11580
|
+
const extractedAttributeOp = createExtractedAttributeOp(op.target, op.isStructuralTemplateAttribute ? BindingKind.Template : BindingKind.Attribute, op.name, op.expression, op.i18nContext, op.i18nMessage, op.securityContext);
|
|
11582
11581
|
if (unit.job.kind === CompilationJobKind.Host) {
|
|
11583
11582
|
// This attribute will apply to the enclosing host binding compilation unit, so order doesn't
|
|
11584
11583
|
// matter.
|
|
@@ -11625,16 +11624,16 @@ function specializeBindings(job) {
|
|
|
11625
11624
|
target.nonBindable = true;
|
|
11626
11625
|
}
|
|
11627
11626
|
else {
|
|
11628
|
-
OpList.replace(op, createAttributeOp(op.target, op.name, op.expression, op.securityContext, op.isTextAttribute, op.
|
|
11627
|
+
OpList.replace(op, createAttributeOp(op.target, op.name, op.expression, op.securityContext, op.isTextAttribute, op.isStructuralTemplateAttribute, op.templateKind, op.i18nMessage, op.sourceSpan));
|
|
11629
11628
|
}
|
|
11630
11629
|
break;
|
|
11631
11630
|
case BindingKind.Property:
|
|
11632
11631
|
case BindingKind.Animation:
|
|
11633
11632
|
if (job.kind === CompilationJobKind.Host) {
|
|
11634
|
-
OpList.replace(op, createHostPropertyOp(op.name, op.expression, op.bindingKind === BindingKind.Animation, op.i18nContext, op.sourceSpan));
|
|
11633
|
+
OpList.replace(op, createHostPropertyOp(op.name, op.expression, op.bindingKind === BindingKind.Animation, op.i18nContext, op.securityContext, op.sourceSpan));
|
|
11635
11634
|
}
|
|
11636
11635
|
else {
|
|
11637
|
-
OpList.replace(op, createPropertyOp(op.target, op.name, op.expression, op.bindingKind === BindingKind.Animation, op.securityContext, op.
|
|
11636
|
+
OpList.replace(op, createPropertyOp(op.target, op.name, op.expression, op.bindingKind === BindingKind.Animation, op.securityContext, op.isStructuralTemplateAttribute, op.templateKind, op.i18nContext, op.i18nMessage, op.sourceSpan));
|
|
11638
11637
|
}
|
|
11639
11638
|
break;
|
|
11640
11639
|
case BindingKind.I18n:
|
|
@@ -11871,7 +11870,7 @@ function collectElementConsts(job) {
|
|
|
11871
11870
|
if (op.kind === OpKind.ExtractedAttribute) {
|
|
11872
11871
|
const attributes = allElementAttributes.get(op.target) || new ElementAttributes();
|
|
11873
11872
|
allElementAttributes.set(op.target, attributes);
|
|
11874
|
-
attributes.add(op.bindingKind, op.name, op.expression);
|
|
11873
|
+
attributes.add(op.bindingKind, op.name, op.expression, op.trustedValueFn);
|
|
11875
11874
|
OpList.remove(op);
|
|
11876
11875
|
}
|
|
11877
11876
|
}
|
|
@@ -11937,11 +11936,12 @@ class ElementAttributes {
|
|
|
11937
11936
|
get i18n() {
|
|
11938
11937
|
return this.byKind.get(BindingKind.I18n) ?? FLYWEIGHT_ARRAY;
|
|
11939
11938
|
}
|
|
11940
|
-
add(kind, name, value) {
|
|
11939
|
+
add(kind, name, value, trustedValueFn) {
|
|
11941
11940
|
if (this.known.has(name)) {
|
|
11942
11941
|
return;
|
|
11943
11942
|
}
|
|
11944
11943
|
this.known.add(name);
|
|
11944
|
+
// TODO: Can this be its own phase
|
|
11945
11945
|
if (name === 'ngProjectAs') {
|
|
11946
11946
|
if (value === null || !(value instanceof LiteralExpr) || (value.value == null) ||
|
|
11947
11947
|
(typeof value.value?.toString() !== 'string')) {
|
|
@@ -11957,7 +11957,15 @@ class ElementAttributes {
|
|
|
11957
11957
|
if (value === null) {
|
|
11958
11958
|
throw Error('Attribute, i18n attribute, & style element attributes must have a value');
|
|
11959
11959
|
}
|
|
11960
|
-
|
|
11960
|
+
if (trustedValueFn !== null) {
|
|
11961
|
+
if (!isStringLiteral(value)) {
|
|
11962
|
+
throw Error('AssertionError: extracted attribute value should be string literal');
|
|
11963
|
+
}
|
|
11964
|
+
array.push(taggedTemplate(trustedValueFn, new TemplateLiteral([new TemplateLiteralElement(value.value)], []), undefined, value.sourceSpan));
|
|
11965
|
+
}
|
|
11966
|
+
else {
|
|
11967
|
+
array.push(value);
|
|
11968
|
+
}
|
|
11961
11969
|
}
|
|
11962
11970
|
}
|
|
11963
11971
|
arrayFor(kind) {
|
|
@@ -12101,6 +12109,9 @@ function createI18nContexts(job) {
|
|
|
12101
12109
|
const rootContexts = new Map();
|
|
12102
12110
|
let currentI18nOp = null;
|
|
12103
12111
|
let xref;
|
|
12112
|
+
// We use the message instead of the message ID, because placeholder values might differ even
|
|
12113
|
+
// when IDs are the same.
|
|
12114
|
+
const messageToContext = new Map();
|
|
12104
12115
|
for (const unit of job.units) {
|
|
12105
12116
|
for (const op of unit.create) {
|
|
12106
12117
|
switch (op.kind) {
|
|
@@ -12138,6 +12149,25 @@ function createI18nContexts(job) {
|
|
|
12138
12149
|
break;
|
|
12139
12150
|
}
|
|
12140
12151
|
}
|
|
12152
|
+
for (const op of unit.ops()) {
|
|
12153
|
+
switch (op.kind) {
|
|
12154
|
+
case OpKind.Binding:
|
|
12155
|
+
case OpKind.Property:
|
|
12156
|
+
case OpKind.Attribute:
|
|
12157
|
+
case OpKind.ExtractedAttribute:
|
|
12158
|
+
if (!op.i18nMessage) {
|
|
12159
|
+
continue;
|
|
12160
|
+
}
|
|
12161
|
+
if (!messageToContext.has(op.i18nMessage)) {
|
|
12162
|
+
// create the context
|
|
12163
|
+
const i18nContext = job.allocateXrefId();
|
|
12164
|
+
unit.create.push(createI18nContextOp(I18nContextKind.Attr, i18nContext, null, op.i18nMessage, null));
|
|
12165
|
+
messageToContext.set(op.i18nMessage, i18nContext);
|
|
12166
|
+
}
|
|
12167
|
+
op.i18nContext = messageToContext.get(op.i18nMessage);
|
|
12168
|
+
break;
|
|
12169
|
+
}
|
|
12170
|
+
}
|
|
12141
12171
|
}
|
|
12142
12172
|
// Assign contexts to child i18n blocks, now that all root i18n blocks have their context
|
|
12143
12173
|
// assigned.
|
|
@@ -12812,9 +12842,15 @@ function recursivelyProcessView(view, parentScope) {
|
|
|
12812
12842
|
for (const op of view.create) {
|
|
12813
12843
|
switch (op.kind) {
|
|
12814
12844
|
case OpKind.Template:
|
|
12845
|
+
// Descend into child embedded views.
|
|
12846
|
+
recursivelyProcessView(view.job.views.get(op.xref), scope);
|
|
12847
|
+
break;
|
|
12815
12848
|
case OpKind.RepeaterCreate:
|
|
12816
12849
|
// Descend into child embedded views.
|
|
12817
12850
|
recursivelyProcessView(view.job.views.get(op.xref), scope);
|
|
12851
|
+
if (op.emptyView) {
|
|
12852
|
+
recursivelyProcessView(view.job.views.get(op.emptyView), scope);
|
|
12853
|
+
}
|
|
12818
12854
|
break;
|
|
12819
12855
|
case OpKind.Listener:
|
|
12820
12856
|
// Prepend variables to listener handler functions.
|
|
@@ -19954,7 +19990,7 @@ const ESCAPE = '\uFFFD';
|
|
|
19954
19990
|
function collectI18nConsts(job) {
|
|
19955
19991
|
const fileBasedI18nSuffix = job.relativeContextFilePath.replace(/[^A-Za-z0-9]/g, '_').toUpperCase() + '_';
|
|
19956
19992
|
// Step One: Build up various lookup maps we need to collect all the consts.
|
|
19957
|
-
// Context Xref -> Extracted Attribute
|
|
19993
|
+
// Context Xref -> Extracted Attribute Ops
|
|
19958
19994
|
const extractedAttributesByI18nContext = new Map();
|
|
19959
19995
|
// Element/ElementStart Xref -> I18n Attributes config op
|
|
19960
19996
|
const i18nAttributesByElement = new Map();
|
|
@@ -19965,7 +20001,9 @@ function collectI18nConsts(job) {
|
|
|
19965
20001
|
for (const unit of job.units) {
|
|
19966
20002
|
for (const op of unit.ops()) {
|
|
19967
20003
|
if (op.kind === OpKind.ExtractedAttribute && op.i18nContext !== null) {
|
|
19968
|
-
extractedAttributesByI18nContext.
|
|
20004
|
+
const attributes = extractedAttributesByI18nContext.get(op.i18nContext) ?? [];
|
|
20005
|
+
attributes.push(op);
|
|
20006
|
+
extractedAttributesByI18nContext.set(op.i18nContext, attributes);
|
|
19969
20007
|
}
|
|
19970
20008
|
else if (op.kind === OpKind.I18nAttributes) {
|
|
19971
20009
|
i18nAttributesByElement.set(op.target, op);
|
|
@@ -20010,9 +20048,11 @@ function collectI18nConsts(job) {
|
|
|
20010
20048
|
i18nValuesByContext.set(op.i18nContext, mainVar);
|
|
20011
20049
|
// This i18n message may correspond to an individual extracted attribute. If so, The
|
|
20012
20050
|
// value of that attribute is updated to read the extracted i18n variable.
|
|
20013
|
-
const
|
|
20014
|
-
if (
|
|
20015
|
-
|
|
20051
|
+
const attributesForMessage = extractedAttributesByI18nContext.get(op.i18nContext);
|
|
20052
|
+
if (attributesForMessage !== undefined) {
|
|
20053
|
+
for (const attr of attributesForMessage) {
|
|
20054
|
+
attr.expression = mainVar.clone();
|
|
20055
|
+
}
|
|
20016
20056
|
}
|
|
20017
20057
|
}
|
|
20018
20058
|
}
|
|
@@ -20800,14 +20840,14 @@ function parseExtractedStyles(job) {
|
|
|
20800
20840
|
if (op.name === 'style') {
|
|
20801
20841
|
const parsedStyles = parse(op.expression.value);
|
|
20802
20842
|
for (let i = 0; i < parsedStyles.length - 1; i += 2) {
|
|
20803
|
-
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.StyleProperty, parsedStyles[i], literal(parsedStyles[i + 1]), null), op);
|
|
20843
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.StyleProperty, parsedStyles[i], literal(parsedStyles[i + 1]), null, null, SecurityContext.STYLE), op);
|
|
20804
20844
|
}
|
|
20805
20845
|
OpList.remove(op);
|
|
20806
20846
|
}
|
|
20807
20847
|
else if (op.name === 'class') {
|
|
20808
20848
|
const parsedClasses = op.expression.value.trim().split(/\s+/g);
|
|
20809
20849
|
for (const parsedClass of parsedClasses) {
|
|
20810
|
-
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.ClassName, parsedClass, null, null), op);
|
|
20850
|
+
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.ClassName, parsedClass, null, null, null, SecurityContext.NONE), op);
|
|
20811
20851
|
}
|
|
20812
20852
|
OpList.remove(op);
|
|
20813
20853
|
}
|
|
@@ -20973,22 +21013,37 @@ function propagateI18nBlocksToTemplates(unit, subTemplateIndex) {
|
|
|
20973
21013
|
i18nBlock = null;
|
|
20974
21014
|
break;
|
|
20975
21015
|
case OpKind.Template:
|
|
20976
|
-
|
|
20977
|
-
|
|
20978
|
-
|
|
20979
|
-
|
|
20980
|
-
|
|
20981
|
-
|
|
20982
|
-
|
|
20983
|
-
|
|
20984
|
-
|
|
21016
|
+
subTemplateIndex = propagateI18nBlocksForView(unit.job.views.get(op.xref), i18nBlock, op.i18nPlaceholder, subTemplateIndex);
|
|
21017
|
+
break;
|
|
21018
|
+
case OpKind.RepeaterCreate:
|
|
21019
|
+
// Propagate i18n blocks to the @for template.
|
|
21020
|
+
const forView = unit.job.views.get(op.xref);
|
|
21021
|
+
subTemplateIndex = propagateI18nBlocksForView(unit.job.views.get(op.xref), i18nBlock, op.i18nPlaceholder, subTemplateIndex);
|
|
21022
|
+
// Then if there's an @empty template, propagate the i18n blocks for it as well.
|
|
21023
|
+
if (op.emptyView !== null) {
|
|
21024
|
+
subTemplateIndex = propagateI18nBlocksForView(unit.job.views.get(op.emptyView), i18nBlock, op.emptyI18nPlaceholder, subTemplateIndex);
|
|
20985
21025
|
}
|
|
20986
|
-
|
|
20987
|
-
subTemplateIndex = propagateI18nBlocksToTemplates(templateView, subTemplateIndex);
|
|
21026
|
+
break;
|
|
20988
21027
|
}
|
|
20989
21028
|
}
|
|
20990
21029
|
return subTemplateIndex;
|
|
20991
21030
|
}
|
|
21031
|
+
/**
|
|
21032
|
+
* Propagate i18n blocks for a view.
|
|
21033
|
+
*/
|
|
21034
|
+
function propagateI18nBlocksForView(view, i18nBlock, i18nPlaceholder, subTemplateIndex) {
|
|
21035
|
+
// We found an <ng-template> inside an i18n block; increment the sub-template counter and
|
|
21036
|
+
// wrap the template's view in a child i18n block.
|
|
21037
|
+
if (i18nPlaceholder !== undefined) {
|
|
21038
|
+
if (i18nBlock === null) {
|
|
21039
|
+
throw Error('Expected template with i18n placeholder to be in an i18n block.');
|
|
21040
|
+
}
|
|
21041
|
+
subTemplateIndex++;
|
|
21042
|
+
wrapTemplateWithI18n(view, i18nBlock);
|
|
21043
|
+
}
|
|
21044
|
+
// Continue traversing inside the template's view.
|
|
21045
|
+
return propagateI18nBlocksToTemplates(view, subTemplateIndex);
|
|
21046
|
+
}
|
|
20992
21047
|
/**
|
|
20993
21048
|
* Wraps a template view with i18n start and end ops.
|
|
20994
21049
|
*/
|
|
@@ -21154,17 +21209,13 @@ function disableBindings() {
|
|
|
21154
21209
|
function enableBindings() {
|
|
21155
21210
|
return call(Identifiers.enableBindings, [], null);
|
|
21156
21211
|
}
|
|
21157
|
-
function listener(name, handlerFn, sourceSpan) {
|
|
21158
|
-
|
|
21159
|
-
|
|
21160
|
-
|
|
21161
|
-
|
|
21162
|
-
}
|
|
21163
|
-
|
|
21164
|
-
return call(Identifiers.syntheticHostListener, [
|
|
21165
|
-
literal(name),
|
|
21166
|
-
handlerFn,
|
|
21167
|
-
], sourceSpan);
|
|
21212
|
+
function listener(name, handlerFn, eventTargetResolver, syntheticHost, sourceSpan) {
|
|
21213
|
+
const args = [literal(name), handlerFn];
|
|
21214
|
+
if (eventTargetResolver !== null) {
|
|
21215
|
+
args.push(literal(false)); // `useCapture` flag, defaults to `false`
|
|
21216
|
+
args.push(importExpr(eventTargetResolver));
|
|
21217
|
+
}
|
|
21218
|
+
return call(syntheticHost ? Identifiers.syntheticHostListener : Identifiers.listener, args, sourceSpan);
|
|
21168
21219
|
}
|
|
21169
21220
|
function pipe(slot, name) {
|
|
21170
21221
|
return call(Identifiers.pipe, [
|
|
@@ -21425,8 +21476,12 @@ function classMapInterpolate(strings, expressions, sourceSpan) {
|
|
|
21425
21476
|
const interpolationArgs = collateInterpolationArgs(strings, expressions);
|
|
21426
21477
|
return callVariadicInstruction(CLASS_MAP_INTERPOLATE_CONFIG, [], interpolationArgs, [], sourceSpan);
|
|
21427
21478
|
}
|
|
21428
|
-
function hostProperty(name, expression, sourceSpan) {
|
|
21429
|
-
|
|
21479
|
+
function hostProperty(name, expression, sanitizer, sourceSpan) {
|
|
21480
|
+
const args = [literal(name), expression];
|
|
21481
|
+
if (sanitizer !== null) {
|
|
21482
|
+
args.push(sanitizer);
|
|
21483
|
+
}
|
|
21484
|
+
return call(Identifiers.hostProperty, args, sourceSpan);
|
|
21430
21485
|
}
|
|
21431
21486
|
function syntheticHostProperty(name, expression, sourceSpan) {
|
|
21432
21487
|
return call(Identifiers.syntheticHostProperty, [literal(name), expression], sourceSpan);
|
|
@@ -21644,14 +21699,12 @@ function callVariadicInstruction(config, baseArgs, interpolationArgs, extraArgs,
|
|
|
21644
21699
|
}
|
|
21645
21700
|
|
|
21646
21701
|
/**
|
|
21647
|
-
* Map of
|
|
21702
|
+
* Map of target resolvers for event listeners.
|
|
21648
21703
|
*/
|
|
21649
|
-
const
|
|
21650
|
-
[
|
|
21651
|
-
[
|
|
21652
|
-
[
|
|
21653
|
-
[SanitizerFn.Script, Identifiers.sanitizeScript],
|
|
21654
|
-
[SanitizerFn.Style, Identifiers.sanitizeStyle], [SanitizerFn.Url, Identifiers.sanitizeUrl]
|
|
21704
|
+
const GLOBAL_TARGET_RESOLVERS$1 = new Map([
|
|
21705
|
+
['window', Identifiers.resolveWindow],
|
|
21706
|
+
['document', Identifiers.resolveDocument],
|
|
21707
|
+
['body', Identifiers.resolveBody],
|
|
21655
21708
|
]);
|
|
21656
21709
|
/**
|
|
21657
21710
|
* Compiles semantic operations across all views and generates output `o.Statement`s with actual
|
|
@@ -21728,10 +21781,11 @@ function reifyCreateOperations(unit, ops) {
|
|
|
21728
21781
|
break;
|
|
21729
21782
|
case OpKind.Listener:
|
|
21730
21783
|
const listenerFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, op.consumesDollarEvent);
|
|
21731
|
-
const
|
|
21732
|
-
|
|
21733
|
-
|
|
21734
|
-
|
|
21784
|
+
const eventTargetResolver = op.eventTarget ? GLOBAL_TARGET_RESOLVERS$1.get(op.eventTarget) : null;
|
|
21785
|
+
if (eventTargetResolver === undefined) {
|
|
21786
|
+
throw new Error(`AssertionError: unknown event target ${op.eventTarget}`);
|
|
21787
|
+
}
|
|
21788
|
+
OpList.replace(op, listener(op.name, listenerFn, eventTargetResolver, op.hostListener && op.isAnimationListener, op.sourceSpan));
|
|
21735
21789
|
break;
|
|
21736
21790
|
case OpKind.Variable:
|
|
21737
21791
|
if (op.variable.name === null) {
|
|
@@ -21894,7 +21948,7 @@ function reifyUpdateOperations(_unit, ops) {
|
|
|
21894
21948
|
OpList.replace(op, syntheticHostProperty(op.name, op.expression, op.sourceSpan));
|
|
21895
21949
|
}
|
|
21896
21950
|
else {
|
|
21897
|
-
OpList.replace(op, hostProperty(op.name, op.expression, op.sourceSpan));
|
|
21951
|
+
OpList.replace(op, hostProperty(op.name, op.expression, op.sanitizer, op.sourceSpan));
|
|
21898
21952
|
}
|
|
21899
21953
|
}
|
|
21900
21954
|
break;
|
|
@@ -21973,8 +22027,6 @@ function reifyIrExpression(expr) {
|
|
|
21973
22027
|
return pipeBind(expr.targetSlot.slot, expr.varOffset, expr.args);
|
|
21974
22028
|
case ExpressionKind.PipeBindingVariadic:
|
|
21975
22029
|
return pipeBindV(expr.targetSlot.slot, expr.varOffset, expr.args);
|
|
21976
|
-
case ExpressionKind.SanitizerExpr:
|
|
21977
|
-
return importExpr(sanitizerIdentifierMap.get(expr.fn));
|
|
21978
22030
|
case ExpressionKind.SlotLiteralExpr:
|
|
21979
22031
|
return literal(expr.slot.slot);
|
|
21980
22032
|
default:
|
|
@@ -22267,10 +22319,11 @@ function resolvePlaceholdersForView(job, unit, i18nContexts, elements, pendingSt
|
|
|
22267
22319
|
}
|
|
22268
22320
|
break;
|
|
22269
22321
|
case OpKind.Template:
|
|
22322
|
+
const view = job.views.get(op.xref);
|
|
22270
22323
|
if (op.i18nPlaceholder === undefined) {
|
|
22271
22324
|
// If there is no i18n placeholder, just recurse into the view in case it contains i18n
|
|
22272
22325
|
// blocks.
|
|
22273
|
-
resolvePlaceholdersForView(job,
|
|
22326
|
+
resolvePlaceholdersForView(job, view, i18nContexts, elements);
|
|
22274
22327
|
}
|
|
22275
22328
|
else {
|
|
22276
22329
|
if (currentOps === null) {
|
|
@@ -22281,14 +22334,59 @@ function resolvePlaceholdersForView(job, unit, i18nContexts, elements, pendingSt
|
|
|
22281
22334
|
// the current template as a pending structural directive to be recorded when we find
|
|
22282
22335
|
// the element, content, or template it belongs to. This allows us to create combined
|
|
22283
22336
|
// values that represent, e.g. the start of a template and element at the same time.
|
|
22284
|
-
resolvePlaceholdersForView(job,
|
|
22337
|
+
resolvePlaceholdersForView(job, view, i18nContexts, elements, op);
|
|
22285
22338
|
}
|
|
22286
22339
|
else {
|
|
22287
22340
|
// If this is some other kind of template, we can record its start, recurse into its
|
|
22288
22341
|
// view, and then record its end.
|
|
22289
|
-
recordTemplateStart(job, op, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22290
|
-
resolvePlaceholdersForView(job,
|
|
22291
|
-
recordTemplateClose(job, op, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22342
|
+
recordTemplateStart(job, view, op.handle.slot, op.i18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22343
|
+
resolvePlaceholdersForView(job, view, i18nContexts, elements);
|
|
22344
|
+
recordTemplateClose(job, view, op.handle.slot, op.i18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22345
|
+
pendingStructuralDirective = undefined;
|
|
22346
|
+
}
|
|
22347
|
+
}
|
|
22348
|
+
break;
|
|
22349
|
+
case OpKind.RepeaterCreate:
|
|
22350
|
+
if (pendingStructuralDirective !== undefined) {
|
|
22351
|
+
throw Error('AssertionError: Unexpected structural directive associated with @for block');
|
|
22352
|
+
}
|
|
22353
|
+
// RepeaterCreate has 3 slots: the first is for the op itself, the second is for the @for
|
|
22354
|
+
// template and the (optional) third is for the @empty template.
|
|
22355
|
+
const forSlot = op.handle.slot + 1;
|
|
22356
|
+
const forView = job.views.get(op.xref);
|
|
22357
|
+
// First record all of the placeholders for the @for template.
|
|
22358
|
+
if (op.i18nPlaceholder === undefined) {
|
|
22359
|
+
// If there is no i18n placeholder, just recurse into the view in case it contains i18n
|
|
22360
|
+
// blocks.
|
|
22361
|
+
resolvePlaceholdersForView(job, forView, i18nContexts, elements);
|
|
22362
|
+
}
|
|
22363
|
+
else {
|
|
22364
|
+
if (currentOps === null) {
|
|
22365
|
+
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
22366
|
+
}
|
|
22367
|
+
recordTemplateStart(job, forView, forSlot, op.i18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22368
|
+
resolvePlaceholdersForView(job, forView, i18nContexts, elements);
|
|
22369
|
+
recordTemplateClose(job, forView, forSlot, op.i18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22370
|
+
pendingStructuralDirective = undefined;
|
|
22371
|
+
}
|
|
22372
|
+
// Then if there's an @empty template, add its placeholders as well.
|
|
22373
|
+
if (op.emptyView !== null) {
|
|
22374
|
+
// RepeaterCreate has 3 slots: the first is for the op itself, the second is for the @for
|
|
22375
|
+
// template and the (optional) third is for the @empty template.
|
|
22376
|
+
const emptySlot = op.handle.slot + 2;
|
|
22377
|
+
const emptyView = job.views.get(op.emptyView);
|
|
22378
|
+
if (op.emptyI18nPlaceholder === undefined) {
|
|
22379
|
+
// If there is no i18n placeholder, just recurse into the view in case it contains i18n
|
|
22380
|
+
// blocks.
|
|
22381
|
+
resolvePlaceholdersForView(job, emptyView, i18nContexts, elements);
|
|
22382
|
+
}
|
|
22383
|
+
else {
|
|
22384
|
+
if (currentOps === null) {
|
|
22385
|
+
throw Error('i18n tag placeholder should only occur inside an i18n block');
|
|
22386
|
+
}
|
|
22387
|
+
recordTemplateStart(job, emptyView, emptySlot, op.emptyI18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22388
|
+
resolvePlaceholdersForView(job, emptyView, i18nContexts, elements);
|
|
22389
|
+
recordTemplateClose(job, emptyView, emptySlot, op.emptyI18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
|
|
22292
22390
|
pendingStructuralDirective = undefined;
|
|
22293
22391
|
}
|
|
22294
22392
|
}
|
|
@@ -22336,8 +22434,8 @@ function recordElementClose(op, i18nContext, i18nBlock, structuralDirective) {
|
|
|
22336
22434
|
/**
|
|
22337
22435
|
* Records an i18n param value for the start of a template.
|
|
22338
22436
|
*/
|
|
22339
|
-
function recordTemplateStart(job,
|
|
22340
|
-
let { startName, closeName } =
|
|
22437
|
+
function recordTemplateStart(job, view, slot, i18nPlaceholder, i18nContext, i18nBlock, structuralDirective) {
|
|
22438
|
+
let { startName, closeName } = i18nPlaceholder;
|
|
22341
22439
|
let flags = I18nParamValueFlags.TemplateTag | I18nParamValueFlags.OpenTag;
|
|
22342
22440
|
// For self-closing tags, there is no close tag placeholder. Instead, the start tag
|
|
22343
22441
|
// placeholder accounts for the start and close of the element.
|
|
@@ -22352,20 +22450,20 @@ function recordTemplateStart(job, op, i18nContext, i18nBlock, structuralDirectiv
|
|
|
22352
22450
|
}
|
|
22353
22451
|
// Record the start of the template. For the sub-template index, pass the index for the template's
|
|
22354
22452
|
// view, rather than the current i18n block's index.
|
|
22355
|
-
addParam(i18nContext.params, startName,
|
|
22453
|
+
addParam(i18nContext.params, startName, slot, getSubTemplateIndexForTemplateTag(job, i18nBlock, view), flags);
|
|
22356
22454
|
}
|
|
22357
22455
|
/**
|
|
22358
22456
|
* Records an i18n param value for the closing of a template.
|
|
22359
22457
|
*/
|
|
22360
|
-
function recordTemplateClose(job,
|
|
22361
|
-
const { startName, closeName } =
|
|
22458
|
+
function recordTemplateClose(job, view, slot, i18nPlaceholder, i18nContext, i18nBlock, structuralDirective) {
|
|
22459
|
+
const { startName, closeName } = i18nPlaceholder;
|
|
22362
22460
|
const flags = I18nParamValueFlags.TemplateTag | I18nParamValueFlags.CloseTag;
|
|
22363
22461
|
// Self-closing tags don't have a closing tag placeholder, instead the template's closing is
|
|
22364
22462
|
// recorded via an additional flag on the template start value.
|
|
22365
22463
|
if (closeName) {
|
|
22366
22464
|
// Record the closing of the template. For the sub-template index, pass the index for the
|
|
22367
22465
|
// template's view, rather than the current i18n block's index.
|
|
22368
|
-
addParam(i18nContext.params, closeName,
|
|
22466
|
+
addParam(i18nContext.params, closeName, slot, getSubTemplateIndexForTemplateTag(job, i18nBlock, view), flags);
|
|
22369
22467
|
// If the template is associated with a structural directive, record the structural directive's
|
|
22370
22468
|
// closing after. Since this template must be in the structural directive's view, we can just
|
|
22371
22469
|
// directly use the current i18n block's sub-template index.
|
|
@@ -22378,8 +22476,8 @@ function recordTemplateClose(job, op, i18nContext, i18nBlock, structuralDirectiv
|
|
|
22378
22476
|
* Get the subTemplateIndex for the given template op. For template ops, use the subTemplateIndex of
|
|
22379
22477
|
* the child i18n block inside the template.
|
|
22380
22478
|
*/
|
|
22381
|
-
function getSubTemplateIndexForTemplateTag(job, i18nOp,
|
|
22382
|
-
for (const childOp of
|
|
22479
|
+
function getSubTemplateIndexForTemplateTag(job, i18nOp, view) {
|
|
22480
|
+
for (const childOp of view.create) {
|
|
22383
22481
|
if (childOp.kind === OpKind.I18nStart) {
|
|
22384
22482
|
return childOp.subTemplateIndex;
|
|
22385
22483
|
}
|
|
@@ -22596,12 +22694,20 @@ function processLexicalScope(unit, ops, savedView) {
|
|
|
22596
22694
|
}
|
|
22597
22695
|
|
|
22598
22696
|
/**
|
|
22599
|
-
*
|
|
22697
|
+
* Map of security contexts to their sanitizer function.
|
|
22698
|
+
*/
|
|
22699
|
+
const sanitizerFns = new Map([
|
|
22700
|
+
[SecurityContext.HTML, Identifiers.sanitizeHtml],
|
|
22701
|
+
[SecurityContext.RESOURCE_URL, Identifiers.sanitizeResourceUrl],
|
|
22702
|
+
[SecurityContext.SCRIPT, Identifiers.sanitizeScript],
|
|
22703
|
+
[SecurityContext.STYLE, Identifiers.sanitizeStyle], [SecurityContext.URL, Identifiers.sanitizeUrl]
|
|
22704
|
+
]);
|
|
22705
|
+
/**
|
|
22706
|
+
* Map of security contexts to their trusted value function.
|
|
22600
22707
|
*/
|
|
22601
|
-
const
|
|
22602
|
-
[SecurityContext.HTML,
|
|
22603
|
-
[SecurityContext.
|
|
22604
|
-
[SecurityContext.RESOURCE_URL, SanitizerFn.ResourceUrl]
|
|
22708
|
+
const trustedValueFns = new Map([
|
|
22709
|
+
[SecurityContext.HTML, Identifiers.trustConstantHtml],
|
|
22710
|
+
[SecurityContext.RESOURCE_URL, Identifiers.trustConstantResourceUrl],
|
|
22605
22711
|
]);
|
|
22606
22712
|
/**
|
|
22607
22713
|
* Resolves sanitization functions for ops that need them.
|
|
@@ -22609,24 +22715,61 @@ const sanitizers = new Map([
|
|
|
22609
22715
|
function resolveSanitizers(job) {
|
|
22610
22716
|
for (const unit of job.units) {
|
|
22611
22717
|
const elements = createOpXrefMap(unit);
|
|
22612
|
-
|
|
22718
|
+
// For normal element bindings we create trusted values for security sensitive constant
|
|
22719
|
+
// attributes. However, for host bindings we skip this step (this matches what
|
|
22720
|
+
// TemplateDefinitionBuilder does).
|
|
22721
|
+
// TODO: Is the TDB behavior correct here?
|
|
22722
|
+
if (job.kind !== CompilationJobKind.Host) {
|
|
22723
|
+
for (const op of unit.create) {
|
|
22724
|
+
if (op.kind === OpKind.ExtractedAttribute) {
|
|
22725
|
+
const trustedValueFn = trustedValueFns.get(getOnlySecurityContext(op.securityContext)) ?? null;
|
|
22726
|
+
op.trustedValueFn = trustedValueFn !== null ? importExpr(trustedValueFn) : null;
|
|
22727
|
+
}
|
|
22728
|
+
}
|
|
22729
|
+
}
|
|
22613
22730
|
for (const op of unit.update) {
|
|
22614
22731
|
switch (op.kind) {
|
|
22615
22732
|
case OpKind.Property:
|
|
22616
22733
|
case OpKind.Attribute:
|
|
22617
|
-
|
|
22618
|
-
|
|
22734
|
+
case OpKind.HostProperty:
|
|
22735
|
+
let sanitizerFn = null;
|
|
22736
|
+
if (Array.isArray(op.securityContext) && op.securityContext.length === 2 &&
|
|
22737
|
+
op.securityContext.indexOf(SecurityContext.URL) > -1 &&
|
|
22738
|
+
op.securityContext.indexOf(SecurityContext.RESOURCE_URL) > -1) {
|
|
22739
|
+
// When the host element isn't known, some URL attributes (such as "src" and "href") may
|
|
22740
|
+
// be part of multiple different security contexts. In this case we use special
|
|
22741
|
+
// sanitization function and select the actual sanitizer at runtime based on a tag name
|
|
22742
|
+
// that is provided while invoking sanitization function.
|
|
22743
|
+
sanitizerFn = Identifiers.sanitizeUrlOrResourceUrl;
|
|
22744
|
+
}
|
|
22745
|
+
else {
|
|
22746
|
+
sanitizerFn = sanitizerFns.get(getOnlySecurityContext(op.securityContext)) ?? null;
|
|
22747
|
+
}
|
|
22748
|
+
op.sanitizer = sanitizerFn !== null ? importExpr(sanitizerFn) : null;
|
|
22619
22749
|
// If there was no sanitization function found based on the security context of an
|
|
22620
22750
|
// attribute/property, check whether this attribute/property is one of the
|
|
22621
22751
|
// security-sensitive <iframe> attributes (and that the current element is actually an
|
|
22622
22752
|
// <iframe>).
|
|
22623
22753
|
if (op.sanitizer === null) {
|
|
22624
|
-
|
|
22625
|
-
if (
|
|
22626
|
-
|
|
22754
|
+
let isIframe = false;
|
|
22755
|
+
if (job.kind === CompilationJobKind.Host || op.kind === OpKind.HostProperty) {
|
|
22756
|
+
// Note: for host bindings defined on a directive, we do not try to find all
|
|
22757
|
+
// possible places where it can be matched, so we can not determine whether
|
|
22758
|
+
// the host element is an <iframe>. In this case, we just assume it is and append a
|
|
22759
|
+
// validation function, which is invoked at runtime and would have access to the
|
|
22760
|
+
// underlying DOM element to check if it's an <iframe> and if so - run extra checks.
|
|
22761
|
+
isIframe = true;
|
|
22762
|
+
}
|
|
22763
|
+
else {
|
|
22764
|
+
// For a normal binding we can just check if the element its on is an iframe.
|
|
22765
|
+
const ownerOp = elements.get(op.target);
|
|
22766
|
+
if (ownerOp === undefined || !isElementOrContainerOp(ownerOp)) {
|
|
22767
|
+
throw Error('Property should have an element-like owner');
|
|
22768
|
+
}
|
|
22769
|
+
isIframe = isIframeElement$1(ownerOp);
|
|
22627
22770
|
}
|
|
22628
|
-
if (
|
|
22629
|
-
op.sanitizer =
|
|
22771
|
+
if (isIframe && isIframeSecuritySensitiveAttr(op.name)) {
|
|
22772
|
+
op.sanitizer = importExpr(Identifiers.validateIframeAttribute);
|
|
22630
22773
|
}
|
|
22631
22774
|
}
|
|
22632
22775
|
break;
|
|
@@ -22640,6 +22783,22 @@ function resolveSanitizers(job) {
|
|
|
22640
22783
|
function isIframeElement$1(op) {
|
|
22641
22784
|
return op.kind === OpKind.ElementStart && op.tag?.toLowerCase() === 'iframe';
|
|
22642
22785
|
}
|
|
22786
|
+
/**
|
|
22787
|
+
* Asserts that there is only a single security context and returns it.
|
|
22788
|
+
*/
|
|
22789
|
+
function getOnlySecurityContext(securityContext) {
|
|
22790
|
+
if (Array.isArray(securityContext)) {
|
|
22791
|
+
if (securityContext.length > 1) {
|
|
22792
|
+
// TODO: What should we do here? TDB just took the first one, but this feels like something we
|
|
22793
|
+
// would want to know about and create a special case for like we did for Url/ResourceUrl. My
|
|
22794
|
+
// guess is that, outside of the Url/ResourceUrl case, this never actually happens. If there
|
|
22795
|
+
// do turn out to be other cases, throwing an error until we can address it feels safer.
|
|
22796
|
+
throw Error(`AssertionError: Ambiguous security context`);
|
|
22797
|
+
}
|
|
22798
|
+
return securityContext[0] || SecurityContext.NONE;
|
|
22799
|
+
}
|
|
22800
|
+
return securityContext;
|
|
22801
|
+
}
|
|
22643
22802
|
|
|
22644
22803
|
/**
|
|
22645
22804
|
* When inside of a listener, we may need access to one or more enclosing views. Therefore, each
|
|
@@ -22743,6 +22902,8 @@ function allocateSlots(job) {
|
|
|
22743
22902
|
// operation itself, so it can be emitted later.
|
|
22744
22903
|
const childView = job.views.get(op.xref);
|
|
22745
22904
|
op.decls = childView.decls;
|
|
22905
|
+
// TODO: currently we handle the decls for the RepeaterCreate empty template in the reify
|
|
22906
|
+
// phase. We should handle that here instead.
|
|
22746
22907
|
}
|
|
22747
22908
|
}
|
|
22748
22909
|
}
|
|
@@ -23066,6 +23227,8 @@ function countVariables(job) {
|
|
|
23066
23227
|
}
|
|
23067
23228
|
const childView = job.views.get(op.xref);
|
|
23068
23229
|
op.vars = childView.vars;
|
|
23230
|
+
// TODO: currently we handle the vars for the RepeaterCreate empty template in the reify
|
|
23231
|
+
// phase. We should handle that here instead.
|
|
23069
23232
|
}
|
|
23070
23233
|
}
|
|
23071
23234
|
}
|
|
@@ -23587,10 +23750,10 @@ const phases = [
|
|
|
23587
23750
|
{ kind: CompilationJobKind.Tmpl, fn: emitNamespaceChanges },
|
|
23588
23751
|
{ kind: CompilationJobKind.Tmpl, fn: propagateI18nBlocks },
|
|
23589
23752
|
{ kind: CompilationJobKind.Tmpl, fn: wrapI18nIcus },
|
|
23590
|
-
{ kind: CompilationJobKind.Tmpl, fn: createI18nContexts },
|
|
23591
23753
|
{ kind: CompilationJobKind.Both, fn: specializeStyleBindings },
|
|
23592
23754
|
{ kind: CompilationJobKind.Both, fn: specializeBindings },
|
|
23593
23755
|
{ kind: CompilationJobKind.Both, fn: extractAttributes },
|
|
23756
|
+
{ kind: CompilationJobKind.Tmpl, fn: createI18nContexts },
|
|
23594
23757
|
{ kind: CompilationJobKind.Both, fn: parseExtractedStyles },
|
|
23595
23758
|
{ kind: CompilationJobKind.Tmpl, fn: removeEmptyBindings },
|
|
23596
23759
|
{ kind: CompilationJobKind.Both, fn: collapseSingletonInterpolations },
|
|
@@ -23608,7 +23771,7 @@ const phases = [
|
|
|
23608
23771
|
{ kind: CompilationJobKind.Tmpl, fn: generateProjectionDefs },
|
|
23609
23772
|
{ kind: CompilationJobKind.Tmpl, fn: generateVariables },
|
|
23610
23773
|
{ kind: CompilationJobKind.Tmpl, fn: saveAndRestoreView },
|
|
23611
|
-
{ kind: CompilationJobKind.
|
|
23774
|
+
{ kind: CompilationJobKind.Both, fn: deleteAnyCasts },
|
|
23612
23775
|
{ kind: CompilationJobKind.Both, fn: resolveDollarEvent },
|
|
23613
23776
|
{ kind: CompilationJobKind.Tmpl, fn: generateRepeaterDerivedVars },
|
|
23614
23777
|
{ kind: CompilationJobKind.Tmpl, fn: generateTrackVariables },
|
|
@@ -23616,7 +23779,7 @@ const phases = [
|
|
|
23616
23779
|
{ kind: CompilationJobKind.Tmpl, fn: resolveDeferTargetNames },
|
|
23617
23780
|
{ kind: CompilationJobKind.Tmpl, fn: optimizeTrackFns },
|
|
23618
23781
|
{ kind: CompilationJobKind.Both, fn: resolveContexts },
|
|
23619
|
-
{ kind: CompilationJobKind.
|
|
23782
|
+
{ kind: CompilationJobKind.Both, fn: resolveSanitizers },
|
|
23620
23783
|
{ kind: CompilationJobKind.Tmpl, fn: liftLocalRefs },
|
|
23621
23784
|
{ kind: CompilationJobKind.Both, fn: generateNullishCoalesceExpressions },
|
|
23622
23785
|
{ kind: CompilationJobKind.Both, fn: expandSafeReads },
|
|
@@ -23752,6 +23915,10 @@ function emitHostBindingFunction(job) {
|
|
|
23752
23915
|
}
|
|
23753
23916
|
|
|
23754
23917
|
const compatibilityMode = CompatibilityMode.TemplateDefinitionBuilder;
|
|
23918
|
+
// Schema containing DOM elements and their properties.
|
|
23919
|
+
const domSchema = new DomElementSchemaRegistry();
|
|
23920
|
+
// Tag name of the `ng-template` element.
|
|
23921
|
+
const NG_TEMPLATE_TAG_NAME$1 = 'ng-template';
|
|
23755
23922
|
/**
|
|
23756
23923
|
* Process a template AST and convert it into a `ComponentCompilation` in the intermediate
|
|
23757
23924
|
* representation.
|
|
@@ -23769,10 +23936,24 @@ function ingestComponent(componentName, template, constantPool, relativeContextF
|
|
|
23769
23936
|
function ingestHostBinding(input, bindingParser, constantPool) {
|
|
23770
23937
|
const job = new HostBindingCompilationJob(input.componentName, constantPool, compatibilityMode);
|
|
23771
23938
|
for (const property of input.properties ?? []) {
|
|
23772
|
-
|
|
23939
|
+
let bindingKind = BindingKind.Property;
|
|
23940
|
+
// TODO: this should really be handled in the parser.
|
|
23941
|
+
if (property.name.startsWith('attr.')) {
|
|
23942
|
+
property.name = property.name.substring('attr.'.length);
|
|
23943
|
+
bindingKind = BindingKind.Attribute;
|
|
23944
|
+
}
|
|
23945
|
+
if (property.isAnimation) {
|
|
23946
|
+
bindingKind = BindingKind.Animation;
|
|
23947
|
+
}
|
|
23948
|
+
const securityContexts = bindingParser
|
|
23949
|
+
.calcPossibleSecurityContexts(input.componentSelector, property.name, bindingKind === BindingKind.Attribute)
|
|
23950
|
+
.filter(context => context !== SecurityContext.NONE);
|
|
23951
|
+
ingestHostProperty(job, property, bindingKind, false, securityContexts);
|
|
23773
23952
|
}
|
|
23774
23953
|
for (const [name, expr] of Object.entries(input.attributes) ?? []) {
|
|
23775
|
-
|
|
23954
|
+
const securityContexts = bindingParser.calcPossibleSecurityContexts(input.componentSelector, name, true)
|
|
23955
|
+
.filter(context => context !== SecurityContext.NONE);
|
|
23956
|
+
ingestHostAttribute(job, name, expr, securityContexts);
|
|
23776
23957
|
}
|
|
23777
23958
|
for (const event of input.events ?? []) {
|
|
23778
23959
|
ingestHostEvent(job, event);
|
|
@@ -23781,7 +23962,7 @@ function ingestHostBinding(input, bindingParser, constantPool) {
|
|
|
23781
23962
|
}
|
|
23782
23963
|
// TODO: We should refactor the parser to use the same types and structures for host bindings as
|
|
23783
23964
|
// with ordinary components. This would allow us to share a lot more ingestion code.
|
|
23784
|
-
function ingestHostProperty(job, property, isTextAttribute) {
|
|
23965
|
+
function ingestHostProperty(job, property, bindingKind, isTextAttribute, securityContexts) {
|
|
23785
23966
|
let expression;
|
|
23786
23967
|
const ast = property.expression.ast;
|
|
23787
23968
|
if (ast instanceof Interpolation$1) {
|
|
@@ -23790,26 +23971,18 @@ function ingestHostProperty(job, property, isTextAttribute) {
|
|
|
23790
23971
|
else {
|
|
23791
23972
|
expression = convertAst(ast, job, property.sourceSpan);
|
|
23792
23973
|
}
|
|
23793
|
-
|
|
23794
|
-
// TODO: this should really be handled in the parser.
|
|
23795
|
-
if (property.name.startsWith('attr.')) {
|
|
23796
|
-
property.name = property.name.substring('attr.'.length);
|
|
23797
|
-
bindingKind = BindingKind.Attribute;
|
|
23798
|
-
}
|
|
23799
|
-
if (property.isAnimation) {
|
|
23800
|
-
bindingKind = BindingKind.Animation;
|
|
23801
|
-
}
|
|
23802
|
-
job.root.update.push(createBindingOp(job.root.xref, bindingKind, property.name, expression, null, SecurityContext
|
|
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));
|
|
23974
|
+
job.root.update.push(createBindingOp(job.root.xref, bindingKind, property.name, expression, null, securityContexts, isTextAttribute, false, null, /* TODO: How do Host bindings handle i18n attrs? */ null, property.sourceSpan));
|
|
23804
23975
|
}
|
|
23805
|
-
function ingestHostAttribute(job, name, value) {
|
|
23806
|
-
const attrBinding = createBindingOp(job.root.xref, BindingKind.Attribute, name, value, null,
|
|
23976
|
+
function ingestHostAttribute(job, name, value, securityContexts) {
|
|
23977
|
+
const attrBinding = createBindingOp(job.root.xref, BindingKind.Attribute, name, value, null, securityContexts, true, false, null,
|
|
23807
23978
|
/* TODO */ null,
|
|
23808
23979
|
/* TODO: host attribute source spans */ null);
|
|
23809
23980
|
job.root.update.push(attrBinding);
|
|
23810
23981
|
}
|
|
23811
23982
|
function ingestHostEvent(job, event) {
|
|
23812
|
-
const
|
|
23983
|
+
const [phase, target] = event.type === 0 /* e.ParsedEventType.Regular */ ? [null, event.targetOrPhase] :
|
|
23984
|
+
[event.targetOrPhase, null];
|
|
23985
|
+
const eventBinding = createListenerOp(job.root.xref, new SlotHandle(), event.name, null, [], phase, target, true, event.sourceSpan);
|
|
23813
23986
|
// TODO: Can this be a chain?
|
|
23814
23987
|
eventBinding.handlerOps.push(createStatementOp(new ReturnStatement(convertAst(event.handler.ast, job, event.sourceSpan), event.handlerSpan)));
|
|
23815
23988
|
job.root.create.push(eventBinding);
|
|
@@ -23866,8 +24039,14 @@ function ingestElement(unit, element) {
|
|
|
23866
24039
|
const [namespaceKey, elementName] = splitNsName(element.name);
|
|
23867
24040
|
const startOp = createElementStartOp(elementName, id, namespaceForKey(namespaceKey), element.i18n instanceof TagPlaceholder ? element.i18n : undefined, element.startSourceSpan);
|
|
23868
24041
|
unit.create.push(startOp);
|
|
23869
|
-
|
|
24042
|
+
ingestElementBindings(unit, startOp, element);
|
|
23870
24043
|
ingestReferences(startOp, element);
|
|
24044
|
+
// Start i18n, if needed, goes after the element create and bindings, but before the nodes
|
|
24045
|
+
let i18nBlockId = null;
|
|
24046
|
+
if (element.i18n instanceof Message) {
|
|
24047
|
+
i18nBlockId = unit.job.allocateXrefId();
|
|
24048
|
+
unit.create.push(createI18nStartOp(i18nBlockId, element.i18n));
|
|
24049
|
+
}
|
|
23871
24050
|
ingestNodes(unit, element.children);
|
|
23872
24051
|
// The source span for the end op is typically the element closing tag. However, if no closing tag
|
|
23873
24052
|
// exists, such as in `<input>`, we use the start source span instead. Usually the start and end
|
|
@@ -23877,9 +24056,7 @@ function ingestElement(unit, element) {
|
|
|
23877
24056
|
const endOp = createElementEndOp(id, element.endSourceSpan ?? element.startSourceSpan);
|
|
23878
24057
|
unit.create.push(endOp);
|
|
23879
24058
|
// If there is an i18n message associated with this element, insert i18n start and end ops.
|
|
23880
|
-
if (
|
|
23881
|
-
const i18nBlockId = unit.job.allocateXrefId();
|
|
23882
|
-
OpList.insertAfter(createI18nStartOp(i18nBlockId, element.i18n), startOp);
|
|
24059
|
+
if (i18nBlockId !== null) {
|
|
23883
24060
|
OpList.insertBefore(createI18nEndOp(i18nBlockId), endOp);
|
|
23884
24061
|
}
|
|
23885
24062
|
}
|
|
@@ -23905,7 +24082,7 @@ function ingestTemplate(unit, tmpl) {
|
|
|
23905
24082
|
const templateKind = isPlainTemplate(tmpl) ? TemplateKind.NgTemplate : TemplateKind.Structural;
|
|
23906
24083
|
const templateOp = createTemplateOp(childView.xref, templateKind, tagNameWithoutNamespace, functionNameSuffix, namespace, i18nPlaceholder, tmpl.startSourceSpan);
|
|
23907
24084
|
unit.create.push(templateOp);
|
|
23908
|
-
|
|
24085
|
+
ingestTemplateBindings(unit, templateOp, tmpl, templateKind);
|
|
23909
24086
|
ingestReferences(templateOp, tmpl);
|
|
23910
24087
|
ingestNodes(childView, tmpl.children);
|
|
23911
24088
|
for (const { name, value } of tmpl.variables) {
|
|
@@ -23921,7 +24098,7 @@ function ingestTemplate(unit, tmpl) {
|
|
|
23921
24098
|
}
|
|
23922
24099
|
}
|
|
23923
24100
|
/**
|
|
23924
|
-
* Ingest a
|
|
24101
|
+
* Ingest a content node from the AST into the given `ViewCompilation`.
|
|
23925
24102
|
*/
|
|
23926
24103
|
function ingestContent(unit, content) {
|
|
23927
24104
|
if (content.i18n !== undefined && !(content.i18n instanceof TagPlaceholder)) {
|
|
@@ -23930,7 +24107,8 @@ function ingestContent(unit, content) {
|
|
|
23930
24107
|
const attrs = content.attributes.flatMap(a => [a.name, a.value]);
|
|
23931
24108
|
const op = createProjectionOp(unit.job.allocateXrefId(), content.selector, content.i18n, attrs, content.sourceSpan);
|
|
23932
24109
|
for (const attr of content.attributes) {
|
|
23933
|
-
|
|
24110
|
+
const securityContext = domSchema.securityContext(content.name, attr.name, true);
|
|
24111
|
+
unit.update.push(createBindingOp(op.xref, BindingKind.Attribute, attr.name, literal(attr.value), null, securityContext, true, false, null, asMessage(attr.i18n), attr.sourceSpan));
|
|
23934
24112
|
}
|
|
23935
24113
|
unit.create.push(op);
|
|
23936
24114
|
}
|
|
@@ -24045,13 +24223,16 @@ function ingestSwitchBlock(unit, switchBlock) {
|
|
|
24045
24223
|
const conditional = createConditionalOp(firstXref, firstSlotHandle, convertAst(switchBlock.expression, unit.job, null), conditions, switchBlock.sourceSpan);
|
|
24046
24224
|
unit.update.push(conditional);
|
|
24047
24225
|
}
|
|
24048
|
-
function ingestDeferView(unit, suffix, children, sourceSpan) {
|
|
24226
|
+
function ingestDeferView(unit, suffix, i18nMeta, children, sourceSpan) {
|
|
24227
|
+
if (i18nMeta !== undefined && !(i18nMeta instanceof BlockPlaceholder)) {
|
|
24228
|
+
throw Error('Unhandled i18n metadata type for defer block');
|
|
24229
|
+
}
|
|
24049
24230
|
if (children === undefined) {
|
|
24050
24231
|
return null;
|
|
24051
24232
|
}
|
|
24052
24233
|
const secondaryView = unit.job.allocateView(unit.xref);
|
|
24053
24234
|
ingestNodes(secondaryView, children);
|
|
24054
|
-
const templateOp = createTemplateOp(secondaryView.xref, TemplateKind.Block, null, `Defer${suffix}`, Namespace.HTML,
|
|
24235
|
+
const templateOp = createTemplateOp(secondaryView.xref, TemplateKind.Block, null, `Defer${suffix}`, Namespace.HTML, i18nMeta, sourceSpan);
|
|
24055
24236
|
unit.create.push(templateOp);
|
|
24056
24237
|
return templateOp;
|
|
24057
24238
|
}
|
|
@@ -24061,10 +24242,10 @@ function ingestDeferBlock(unit, deferBlock) {
|
|
|
24061
24242
|
throw new Error(`AssertionError: unable to find metadata for deferred block`);
|
|
24062
24243
|
}
|
|
24063
24244
|
// Generate the defer main view and all secondary views.
|
|
24064
|
-
const main = ingestDeferView(unit, '', deferBlock.children, deferBlock.sourceSpan);
|
|
24065
|
-
const loading = ingestDeferView(unit, 'Loading', deferBlock.loading?.children, deferBlock.loading?.sourceSpan);
|
|
24066
|
-
const placeholder = ingestDeferView(unit, 'Placeholder', deferBlock.placeholder?.children, deferBlock.placeholder?.sourceSpan);
|
|
24067
|
-
const error = ingestDeferView(unit, 'Error', deferBlock.error?.children, deferBlock.error?.sourceSpan);
|
|
24245
|
+
const main = ingestDeferView(unit, '', deferBlock.i18n, deferBlock.children, deferBlock.sourceSpan);
|
|
24246
|
+
const loading = ingestDeferView(unit, 'Loading', deferBlock.loading?.i18n, deferBlock.loading?.children, deferBlock.loading?.sourceSpan);
|
|
24247
|
+
const placeholder = ingestDeferView(unit, 'Placeholder', deferBlock.placeholder?.i18n, deferBlock.placeholder?.children, deferBlock.placeholder?.sourceSpan);
|
|
24248
|
+
const error = ingestDeferView(unit, 'Error', deferBlock.error?.i18n, deferBlock.error?.children, deferBlock.error?.sourceSpan);
|
|
24068
24249
|
// Create the main defer op, and ops for all secondary views.
|
|
24069
24250
|
const deferXref = unit.job.allocateXrefId();
|
|
24070
24251
|
const deferOp = createDeferOp(deferXref, main.xref, main.handle, blockMeta, deferBlock.sourceSpan);
|
|
@@ -24198,8 +24379,17 @@ function ingestForBlock(unit, forBlock) {
|
|
|
24198
24379
|
$odd: forBlock.contextVariables.$odd.name,
|
|
24199
24380
|
$implicit: forBlock.item.name,
|
|
24200
24381
|
};
|
|
24382
|
+
if (forBlock.i18n !== undefined && !(forBlock.i18n instanceof BlockPlaceholder)) {
|
|
24383
|
+
throw Error('AssertionError: Unhandled i18n metadata type or @for');
|
|
24384
|
+
}
|
|
24385
|
+
if (forBlock.empty?.i18n !== undefined &&
|
|
24386
|
+
!(forBlock.empty.i18n instanceof BlockPlaceholder)) {
|
|
24387
|
+
throw Error('AssertionError: Unhandled i18n metadata type or @empty');
|
|
24388
|
+
}
|
|
24389
|
+
const i18nPlaceholder = forBlock.i18n;
|
|
24390
|
+
const emptyI18nPlaceholder = forBlock.empty?.i18n;
|
|
24201
24391
|
const tagName = ingestControlFlowInsertionPoint(unit, repeaterView.xref, forBlock);
|
|
24202
|
-
const repeaterCreate = createRepeaterCreateOp(repeaterView.xref, emptyView?.xref ?? null, tagName, track, varNames, forBlock.sourceSpan);
|
|
24392
|
+
const repeaterCreate = createRepeaterCreateOp(repeaterView.xref, emptyView?.xref ?? null, tagName, track, varNames, i18nPlaceholder, emptyI18nPlaceholder, forBlock.sourceSpan);
|
|
24203
24393
|
unit.create.push(repeaterCreate);
|
|
24204
24394
|
const expression = convertAst(forBlock.expression, unit.job, convertSourceSpan(forBlock.expression.span, forBlock.sourceSpan));
|
|
24205
24395
|
const repeater = createRepeaterOp(repeaterCreate.xref, repeaterCreate.handle, expression, forBlock.sourceSpan);
|
|
@@ -24317,6 +24507,27 @@ function convertAst(ast, job, baseSourceSpan) {
|
|
|
24317
24507
|
throw new Error(`Unhandled expression type "${ast.constructor.name}" in file "${baseSourceSpan?.start.file.url}"`);
|
|
24318
24508
|
}
|
|
24319
24509
|
}
|
|
24510
|
+
function convertAstWithInterpolation(job, value, i18nMeta) {
|
|
24511
|
+
let expression;
|
|
24512
|
+
if (value instanceof Interpolation$1) {
|
|
24513
|
+
expression = new Interpolation(value.strings, value.expressions.map(e => convertAst(e, job, null)), Object.keys(asMessage(i18nMeta)?.placeholders ?? {}));
|
|
24514
|
+
}
|
|
24515
|
+
else if (value instanceof AST) {
|
|
24516
|
+
expression = convertAst(value, job, null);
|
|
24517
|
+
}
|
|
24518
|
+
else {
|
|
24519
|
+
expression = literal(value);
|
|
24520
|
+
}
|
|
24521
|
+
return expression;
|
|
24522
|
+
}
|
|
24523
|
+
// TODO: Can we populate Template binding kinds in ingest?
|
|
24524
|
+
const BINDING_KINDS = new Map([
|
|
24525
|
+
[0 /* e.BindingType.Property */, BindingKind.Property],
|
|
24526
|
+
[1 /* e.BindingType.Attribute */, BindingKind.Attribute],
|
|
24527
|
+
[2 /* e.BindingType.Class */, BindingKind.ClassName],
|
|
24528
|
+
[3 /* e.BindingType.Style */, BindingKind.StyleProperty],
|
|
24529
|
+
[4 /* e.BindingType.Animation */, BindingKind.Animation],
|
|
24530
|
+
]);
|
|
24320
24531
|
/**
|
|
24321
24532
|
* Checks whether the given template is a plain ng-template (as opposed to another kind of template
|
|
24322
24533
|
* such as a structural directive template or control flow template). This is checked based on the
|
|
@@ -24335,149 +24546,184 @@ function convertAst(ast, job, baseSourceSpan) {
|
|
|
24335
24546
|
* | `<ng-template *ngIf>` (structural) | null |
|
|
24336
24547
|
*/
|
|
24337
24548
|
function isPlainTemplate(tmpl) {
|
|
24338
|
-
return splitNsName(tmpl.tagName ?? '')[1] ===
|
|
24549
|
+
return splitNsName(tmpl.tagName ?? '')[1] === NG_TEMPLATE_TAG_NAME$1;
|
|
24339
24550
|
}
|
|
24340
24551
|
/**
|
|
24341
|
-
*
|
|
24342
|
-
* to their IR representation.
|
|
24552
|
+
* Ensures that the i18nMeta, if provided, is an i18n.Message.
|
|
24343
24553
|
*/
|
|
24344
|
-
function
|
|
24345
|
-
|
|
24346
|
-
|
|
24347
|
-
|
|
24348
|
-
|
|
24349
|
-
|
|
24350
|
-
flags |= BindingFlags.BindingTargetsTemplate;
|
|
24351
|
-
}
|
|
24352
|
-
const templateAttrFlags = flags | BindingFlags.BindingTargetsTemplate | BindingFlags.IsStructuralTemplateAttribute;
|
|
24353
|
-
for (const attr of element.templateAttrs) {
|
|
24354
|
-
if (attr instanceof TextAttribute) {
|
|
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;
|
|
24357
|
-
}
|
|
24358
|
-
else {
|
|
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;
|
|
24361
|
-
}
|
|
24362
|
-
}
|
|
24554
|
+
function asMessage(i18nMeta) {
|
|
24555
|
+
if (i18nMeta == null) {
|
|
24556
|
+
return null;
|
|
24557
|
+
}
|
|
24558
|
+
if (!(i18nMeta instanceof Message)) {
|
|
24559
|
+
throw Error(`Expected i18n meta to be a Message, but got: ${i18nMeta.constructor.name}`);
|
|
24363
24560
|
}
|
|
24561
|
+
return i18nMeta;
|
|
24562
|
+
}
|
|
24563
|
+
/**
|
|
24564
|
+
* Process all of the bindings on an element in the template AST and convert them to their IR
|
|
24565
|
+
* representation.
|
|
24566
|
+
*/
|
|
24567
|
+
function ingestElementBindings(unit, op, element) {
|
|
24568
|
+
let bindings = new Array();
|
|
24364
24569
|
for (const attr of element.attributes) {
|
|
24365
|
-
//
|
|
24366
|
-
|
|
24367
|
-
|
|
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;
|
|
24570
|
+
// Attribute literal bindings, such as `attr.foo="bar"`.
|
|
24571
|
+
const securityContext = domSchema.securityContext(element.name, attr.name, true);
|
|
24572
|
+
bindings.push(createBindingOp(op.xref, BindingKind.Attribute, attr.name, convertAstWithInterpolation(unit.job, attr.value, attr.i18n), null, securityContext, true, false, null, asMessage(attr.i18n), attr.sourceSpan));
|
|
24370
24573
|
}
|
|
24371
24574
|
for (const input of element.inputs) {
|
|
24372
|
-
|
|
24373
|
-
|
|
24575
|
+
// All dynamic bindings (both attribute and property bindings).
|
|
24576
|
+
bindings.push(createBindingOp(op.xref, BINDING_KINDS.get(input.type), input.name, convertAstWithInterpolation(unit.job, astOf(input.value), input.i18n), input.unit, input.securityContext, false, false, null, asMessage(input.i18n) ?? null, input.sourceSpan));
|
|
24374
24577
|
}
|
|
24578
|
+
unit.create.push(bindings.filter((b) => b?.kind === OpKind.ExtractedAttribute));
|
|
24579
|
+
unit.update.push(bindings.filter((b) => b?.kind === OpKind.Binding));
|
|
24375
24580
|
for (const output of element.outputs) {
|
|
24376
|
-
|
|
24377
|
-
|
|
24378
|
-
if (output.phase === null) {
|
|
24379
|
-
throw Error('Animation listener should have a phase');
|
|
24380
|
-
}
|
|
24381
|
-
}
|
|
24382
|
-
if (element instanceof Template && !isPlainTemplate(element)) {
|
|
24383
|
-
unit.create.push(createExtractedAttributeOp(op.xref, BindingKind.Property, output.name, null, null));
|
|
24384
|
-
continue;
|
|
24385
|
-
}
|
|
24386
|
-
listenerOp = createListenerOp(op.xref, op.handle, output.name, op.tag, output.phase, false, output.sourceSpan);
|
|
24387
|
-
// if output.handler is a chain, then push each statement from the chain separately, and
|
|
24388
|
-
// return the last one?
|
|
24389
|
-
let handlerExprs;
|
|
24390
|
-
let handler = output.handler;
|
|
24391
|
-
if (handler instanceof ASTWithSource) {
|
|
24392
|
-
handler = handler.ast;
|
|
24581
|
+
if (output.type === 1 /* e.ParsedEventType.Animation */ && output.phase === null) {
|
|
24582
|
+
throw Error('Animation listener should have a phase');
|
|
24393
24583
|
}
|
|
24394
|
-
|
|
24395
|
-
|
|
24584
|
+
unit.create.push(createListenerOp(op.xref, op.handle, output.name, op.tag, makeListenerHandlerOps(unit, output.handler, output.handlerSpan), output.phase, output.target, false, output.sourceSpan));
|
|
24585
|
+
}
|
|
24586
|
+
// If any of the bindings on this element have an i18n message, then an i18n attrs configuration
|
|
24587
|
+
// op is also required.
|
|
24588
|
+
if (bindings.some(b => b?.i18nMessage) !== null) {
|
|
24589
|
+
unit.create.push(createI18nAttributesOp(unit.job.allocateXrefId(), new SlotHandle(), op.xref));
|
|
24590
|
+
}
|
|
24591
|
+
}
|
|
24592
|
+
/**
|
|
24593
|
+
* Process all of the bindings on a template in the template AST and convert them to their IR
|
|
24594
|
+
* representation.
|
|
24595
|
+
*/
|
|
24596
|
+
function ingestTemplateBindings(unit, op, template, templateKind) {
|
|
24597
|
+
let bindings = new Array();
|
|
24598
|
+
for (const attr of template.templateAttrs) {
|
|
24599
|
+
if (attr instanceof TextAttribute) {
|
|
24600
|
+
const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME$1, attr.name, true);
|
|
24601
|
+
bindings.push(createTemplateBinding(unit, op.xref, 1 /* e.BindingType.Attribute */, attr.name, attr.value, null, securityContext, true, templateKind, asMessage(attr.i18n), attr.sourceSpan));
|
|
24396
24602
|
}
|
|
24397
24603
|
else {
|
|
24398
|
-
|
|
24604
|
+
bindings.push(createTemplateBinding(unit, op.xref, attr.type, attr.name, astOf(attr.value), attr.unit, attr.securityContext, true, templateKind, asMessage(attr.i18n), attr.sourceSpan));
|
|
24605
|
+
}
|
|
24606
|
+
}
|
|
24607
|
+
for (const attr of template.attributes) {
|
|
24608
|
+
// Attribute literal bindings, such as `attr.foo="bar"`.
|
|
24609
|
+
const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME$1, attr.name, true);
|
|
24610
|
+
bindings.push(createTemplateBinding(unit, op.xref, 1 /* e.BindingType.Attribute */, attr.name, attr.value, null, securityContext, false, templateKind, asMessage(attr.i18n), attr.sourceSpan));
|
|
24611
|
+
}
|
|
24612
|
+
for (const input of template.inputs) {
|
|
24613
|
+
// Dynamic bindings (both attribute and property bindings).
|
|
24614
|
+
bindings.push(createTemplateBinding(unit, op.xref, input.type, input.name, astOf(input.value), input.unit, input.securityContext, false, templateKind, asMessage(input.i18n), input.sourceSpan));
|
|
24615
|
+
}
|
|
24616
|
+
unit.create.push(bindings.filter((b) => b?.kind === OpKind.ExtractedAttribute));
|
|
24617
|
+
unit.update.push(bindings.filter((b) => b?.kind === OpKind.Binding));
|
|
24618
|
+
for (const output of template.outputs) {
|
|
24619
|
+
if (output.type === 1 /* e.ParsedEventType.Animation */ && output.phase === null) {
|
|
24620
|
+
throw Error('Animation listener should have a phase');
|
|
24399
24621
|
}
|
|
24400
|
-
if (
|
|
24401
|
-
|
|
24622
|
+
if (templateKind === TemplateKind.NgTemplate) {
|
|
24623
|
+
unit.create.push(createListenerOp(op.xref, op.handle, output.name, op.tag, makeListenerHandlerOps(unit, output.handler, output.handlerSpan), output.phase, output.target, false, output.sourceSpan));
|
|
24402
24624
|
}
|
|
24403
|
-
|
|
24404
|
-
|
|
24405
|
-
|
|
24406
|
-
const
|
|
24407
|
-
|
|
24625
|
+
if (templateKind === TemplateKind.Structural &&
|
|
24626
|
+
output.type !== 1 /* e.ParsedEventType.Animation */) {
|
|
24627
|
+
// Animation bindings are excluded from the structural template's const array.
|
|
24628
|
+
const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME$1, output.name, false);
|
|
24629
|
+
unit.create.push(createExtractedAttributeOp(op.xref, BindingKind.Property, output.name, null, null, null, securityContext));
|
|
24408
24630
|
}
|
|
24409
|
-
listenerOp.handlerOps.push(createStatementOp(new ReturnStatement(returnExpr, returnExpr.sourceSpan)));
|
|
24410
|
-
unit.create.push(listenerOp);
|
|
24411
24631
|
}
|
|
24412
24632
|
// TODO: Perhaps we could do this in a phase? (It likely wouldn't change the slot indices.)
|
|
24413
|
-
if (
|
|
24633
|
+
if (bindings.some(b => b?.i18nMessage) !== null) {
|
|
24414
24634
|
unit.create.push(createI18nAttributesOp(unit.job.allocateXrefId(), new SlotHandle(), op.xref));
|
|
24415
24635
|
}
|
|
24416
24636
|
}
|
|
24417
|
-
|
|
24418
|
-
|
|
24419
|
-
|
|
24420
|
-
|
|
24421
|
-
|
|
24422
|
-
|
|
24423
|
-
|
|
24424
|
-
|
|
24425
|
-
|
|
24426
|
-
|
|
24427
|
-
|
|
24428
|
-
|
|
24429
|
-
|
|
24430
|
-
|
|
24431
|
-
|
|
24432
|
-
|
|
24433
|
-
|
|
24434
|
-
|
|
24435
|
-
|
|
24436
|
-
|
|
24437
|
-
|
|
24438
|
-
|
|
24439
|
-
|
|
24440
|
-
|
|
24441
|
-
|
|
24442
|
-
|
|
24443
|
-
|
|
24444
|
-
|
|
24445
|
-
|
|
24446
|
-
|
|
24447
|
-
|
|
24448
|
-
|
|
24449
|
-
if (
|
|
24450
|
-
if (!
|
|
24451
|
-
|
|
24637
|
+
/**
|
|
24638
|
+
* Helper to ingest an individual binding on a template, either an explicit `ng-template`, or an
|
|
24639
|
+
* implicit template created via structural directive.
|
|
24640
|
+
*
|
|
24641
|
+
* Bindings on templates are *extremely* tricky. I have tried to isolate all of the confusing edge
|
|
24642
|
+
* cases into this function, and to comment it well to document the behavior.
|
|
24643
|
+
*
|
|
24644
|
+
* Some of this behavior is intuitively incorrect, and we should consider changing it in the future.
|
|
24645
|
+
*
|
|
24646
|
+
* @param view The compilation unit for the view containing the template.
|
|
24647
|
+
* @param xref The xref of the template op.
|
|
24648
|
+
* @param type The binding type, according to the parser. This is fairly reasonable, e.g. both
|
|
24649
|
+
* dynamic and static attributes have e.BindingType.Attribute.
|
|
24650
|
+
* @param name The binding's name.
|
|
24651
|
+
* @param value The bindings's value, which will either be an input AST expression, or a string
|
|
24652
|
+
* literal. Note that the input AST expression may or may not be const -- it will only be a
|
|
24653
|
+
* string literal if the parser considered it a text binding.
|
|
24654
|
+
* @param unit If the binding has a unit (e.g. `px` for style bindings), then this is the unit.
|
|
24655
|
+
* @param securityContext The security context of the binding.
|
|
24656
|
+
* @param isStructuralTemplateAttribute Whether this binding actually applies to the structural
|
|
24657
|
+
* ng-template. For example, an `ngFor` would actually apply to the structural template. (Most
|
|
24658
|
+
* bindings on structural elements target the inner element, not the template.)
|
|
24659
|
+
* @param templateKind Whether this is an explicit `ng-template` or an implicit template created by
|
|
24660
|
+
* a structural directive. This should never be a block template.
|
|
24661
|
+
* @param i18nMessage The i18n metadata for the binding, if any.
|
|
24662
|
+
* @param sourceSpan The source span of the binding.
|
|
24663
|
+
* @returns An IR binding op, or null if the binding should be skipped.
|
|
24664
|
+
*/
|
|
24665
|
+
function createTemplateBinding(view, xref, type, name, value, unit, securityContext, isStructuralTemplateAttribute, templateKind, i18nMessage, sourceSpan) {
|
|
24666
|
+
const isTextBinding = typeof value === 'string';
|
|
24667
|
+
// If this is a structural template, then several kinds of bindings should not result in an
|
|
24668
|
+
// update instruction.
|
|
24669
|
+
if (templateKind === TemplateKind.Structural) {
|
|
24670
|
+
if (!isStructuralTemplateAttribute &&
|
|
24671
|
+
(type === 0 /* e.BindingType.Property */ || type === 2 /* e.BindingType.Class */ ||
|
|
24672
|
+
type === 3 /* e.BindingType.Style */)) {
|
|
24673
|
+
// Because this binding doesn't really target the ng-template, it must be a binding on an
|
|
24674
|
+
// inner node of a structural template. We can't skip it entirely, because we still need it on
|
|
24675
|
+
// the ng-template's consts (e.g. for the purposes of directive matching). However, we should
|
|
24676
|
+
// not generate an update instruction for it.
|
|
24677
|
+
return createExtractedAttributeOp(xref, BindingKind.Property, name, null, null, i18nMessage, securityContext);
|
|
24678
|
+
}
|
|
24679
|
+
if (!isTextBinding && (type === 1 /* e.BindingType.Attribute */ || type === 4 /* e.BindingType.Animation */)) {
|
|
24680
|
+
// Again, this binding doesn't really target the ng-template; it actually targets the element
|
|
24681
|
+
// inside the structural template. In the case of non-text attribute or animation bindings,
|
|
24682
|
+
// the binding doesn't even show up on the ng-template const array, so we just skip it
|
|
24683
|
+
// entirely.
|
|
24684
|
+
return null;
|
|
24452
24685
|
}
|
|
24453
|
-
i18nContext = view.job.allocateXrefId();
|
|
24454
|
-
view.create.push(createI18nContextOp(I18nContextKind.Attr, i18nContext, null, i18nMeta, null));
|
|
24455
|
-
}
|
|
24456
|
-
if (flags & BindingFlags.OnNgTemplateElement && !(flags & BindingFlags.BindingTargetsTemplate) &&
|
|
24457
|
-
type === 0 /* e.BindingType.Property */) {
|
|
24458
|
-
// This binding only exists for later const extraction, and is not an actual binding to be
|
|
24459
|
-
// created.
|
|
24460
|
-
view.create.push(createExtractedAttributeOp(xref, BindingKind.Property, name, null, i18nContext));
|
|
24461
|
-
return;
|
|
24462
24686
|
}
|
|
24463
|
-
let
|
|
24464
|
-
|
|
24465
|
-
|
|
24466
|
-
|
|
24467
|
-
|
|
24468
|
-
|
|
24469
|
-
|
|
24687
|
+
let bindingType = BINDING_KINDS.get(type);
|
|
24688
|
+
if (templateKind === TemplateKind.NgTemplate) {
|
|
24689
|
+
// We know we are dealing with bindings directly on an explicit ng-template.
|
|
24690
|
+
// Static attribute bindings should be collected into the const array as k/v pairs. Property
|
|
24691
|
+
// bindings should result in a `property` instruction, and `AttributeMarker.Bindings` const
|
|
24692
|
+
// entries.
|
|
24693
|
+
//
|
|
24694
|
+
// The difficulty is with dynamic attribute, style, and class bindings. These don't really make
|
|
24695
|
+
// sense on an `ng-template` and should probably be parser errors. However,
|
|
24696
|
+
// TemplateDefinitionBuilder generates `property` instructions for them, and so we do that as
|
|
24697
|
+
// well.
|
|
24698
|
+
//
|
|
24699
|
+
// Note that we do have a slight behavior difference with TemplateDefinitionBuilder: although
|
|
24700
|
+
// TDB emits `property` instructions for dynamic attributes, styles, and classes, only styles
|
|
24701
|
+
// and classes also get const collected into the `AttributeMarker.Bindings` field. Dynamic
|
|
24702
|
+
// attribute bindings are missing from the consts entirely. We choose to emit them into the
|
|
24703
|
+
// consts field anyway, to avoid creating special cases for something so arcane and nonsensical.
|
|
24704
|
+
if (type === 2 /* e.BindingType.Class */ || type === 3 /* e.BindingType.Style */ ||
|
|
24705
|
+
(type === 1 /* e.BindingType.Attribute */ && !isTextBinding)) {
|
|
24706
|
+
// TODO: These cases should be parse errors.
|
|
24707
|
+
bindingType = BindingKind.Property;
|
|
24470
24708
|
}
|
|
24471
|
-
expression = new Interpolation(value.strings, value.expressions.map(expr => convertAst(expr, view.job, null)), i18nPlaceholders);
|
|
24472
24709
|
}
|
|
24473
|
-
|
|
24474
|
-
|
|
24475
|
-
|
|
24476
|
-
|
|
24477
|
-
|
|
24710
|
+
return createBindingOp(xref, bindingType, name, convertAstWithInterpolation(view.job, value, i18nMessage), unit, securityContext, isTextBinding, isStructuralTemplateAttribute, templateKind, i18nMessage, sourceSpan);
|
|
24711
|
+
}
|
|
24712
|
+
function makeListenerHandlerOps(unit, handler, handlerSpan) {
|
|
24713
|
+
handler = astOf(handler);
|
|
24714
|
+
const handlerOps = new Array();
|
|
24715
|
+
let handlerExprs = handler instanceof Chain ? handler.expressions : [handler];
|
|
24716
|
+
if (handlerExprs.length === 0) {
|
|
24717
|
+
throw new Error('Expected listener to have non-empty expression list.');
|
|
24478
24718
|
}
|
|
24479
|
-
const
|
|
24480
|
-
|
|
24719
|
+
const expressions = handlerExprs.map(expr => convertAst(expr, unit.job, handlerSpan));
|
|
24720
|
+
const returnExpr = expressions.pop();
|
|
24721
|
+
handlerOps.push(...expressions.map(e => createStatementOp(new ExpressionStatement(e, e.sourceSpan))));
|
|
24722
|
+
handlerOps.push(createStatementOp(new ReturnStatement(returnExpr, returnExpr.sourceSpan)));
|
|
24723
|
+
return handlerOps;
|
|
24724
|
+
}
|
|
24725
|
+
function astOf(ast) {
|
|
24726
|
+
return ast instanceof ASTWithSource ? ast.ast : ast;
|
|
24481
24727
|
}
|
|
24482
24728
|
/**
|
|
24483
24729
|
* Process all of the local references on an element-like structure in the template AST and
|
|
@@ -24565,11 +24811,12 @@ function ingestControlFlowInsertionPoint(unit, xref, node) {
|
|
|
24565
24811
|
// and they can be used in directive matching (in the case of `Template.templateAttrs`).
|
|
24566
24812
|
if (root !== null) {
|
|
24567
24813
|
for (const attr of root.attributes) {
|
|
24568
|
-
|
|
24814
|
+
const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME$1, attr.name, true);
|
|
24815
|
+
unit.update.push(createBindingOp(xref, BindingKind.Attribute, attr.name, literal(attr.value), null, securityContext, true, false, null, asMessage(attr.i18n), attr.sourceSpan));
|
|
24569
24816
|
}
|
|
24570
24817
|
const tagName = root instanceof Element$1 ? root.name : root.tagName;
|
|
24571
24818
|
// Don't pass along `ng-template` tag name since it enables directive matching.
|
|
24572
|
-
return tagName ===
|
|
24819
|
+
return tagName === NG_TEMPLATE_TAG_NAME$1 ? null : tagName;
|
|
24573
24820
|
}
|
|
24574
24821
|
return null;
|
|
24575
24822
|
}
|
|
@@ -29923,14 +30170,16 @@ function createBaseDirectiveTypeParams(meta) {
|
|
|
29923
30170
|
function getInputsTypeExpression(meta) {
|
|
29924
30171
|
return literalMap(Object.keys(meta.inputs).map(key => {
|
|
29925
30172
|
const value = meta.inputs[key];
|
|
29926
|
-
|
|
29927
|
-
key,
|
|
29928
|
-
value:
|
|
29929
|
-
|
|
29930
|
-
|
|
29931
|
-
|
|
29932
|
-
|
|
29933
|
-
|
|
30173
|
+
const values = [
|
|
30174
|
+
{ key: 'alias', value: literal(value.bindingPropertyName), quoted: true },
|
|
30175
|
+
{ key: 'required', value: literal(value.required), quoted: true },
|
|
30176
|
+
];
|
|
30177
|
+
// TODO(legacy-partial-output-inputs): Consider always emitting this information,
|
|
30178
|
+
// or leaving it as is.
|
|
30179
|
+
if (value.isSignal) {
|
|
30180
|
+
values.push({ key: 'isSignal', value: literal(value.isSignal), quoted: true });
|
|
30181
|
+
}
|
|
30182
|
+
return { key, value: literalMap(values), quoted: true };
|
|
29934
30183
|
}));
|
|
29935
30184
|
}
|
|
29936
30185
|
/**
|
|
@@ -29996,6 +30245,7 @@ function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindin
|
|
|
29996
30245
|
}
|
|
29997
30246
|
const hostJob = ingestHostBinding({
|
|
29998
30247
|
componentName: name,
|
|
30248
|
+
componentSelector: selector,
|
|
29999
30249
|
properties: bindings,
|
|
30000
30250
|
events: eventBindings,
|
|
30001
30251
|
attributes: hostBindingsMetadata.attributes,
|
|
@@ -30306,6 +30556,18 @@ function compileStyles(styles, selector, hostSelector) {
|
|
|
30306
30556
|
return shadowCss.shimCssText(style, selector, hostSelector);
|
|
30307
30557
|
});
|
|
30308
30558
|
}
|
|
30559
|
+
/**
|
|
30560
|
+
* Encapsulates a CSS stylesheet with emulated view encapsulation.
|
|
30561
|
+
* This allows a stylesheet to be used with an Angular component that
|
|
30562
|
+
* is using the `ViewEncapsulation.Emulated` mode.
|
|
30563
|
+
*
|
|
30564
|
+
* @param style The content of a CSS stylesheet.
|
|
30565
|
+
* @returns The encapsulated content for the style.
|
|
30566
|
+
*/
|
|
30567
|
+
function encapsulateStyle(style) {
|
|
30568
|
+
const shadowCss = new ShadowCss();
|
|
30569
|
+
return shadowCss.shimCssText(style, CONTENT_ATTR, HOST_ATTR);
|
|
30570
|
+
}
|
|
30309
30571
|
function createHostDirectivesType(meta) {
|
|
30310
30572
|
if (!meta.hostDirectives?.length) {
|
|
30311
30573
|
return NONE_TYPE;
|
|
@@ -31371,6 +31633,8 @@ function convertDirectiveFacadeToMetadata(facade) {
|
|
|
31371
31633
|
bindingPropertyName: ann.alias || field,
|
|
31372
31634
|
classPropertyName: field,
|
|
31373
31635
|
required: ann.required || false,
|
|
31636
|
+
// TODO(signals): Support JIT signal inputs via decorator transform.
|
|
31637
|
+
isSignal: false,
|
|
31374
31638
|
transformFunction: ann.transform != null ? new WrappedNodeExpr(ann.transform) : null,
|
|
31375
31639
|
};
|
|
31376
31640
|
}
|
|
@@ -31402,7 +31666,7 @@ function convertDeclareDirectiveFacadeToMetadata(declaration, typeSourceSpan) {
|
|
|
31402
31666
|
type: wrapReference(declaration.type),
|
|
31403
31667
|
typeSourceSpan,
|
|
31404
31668
|
selector: declaration.selector ?? null,
|
|
31405
|
-
inputs: declaration.inputs ?
|
|
31669
|
+
inputs: declaration.inputs ? inputsPartialMetadataToInputMetadata(declaration.inputs) : {},
|
|
31406
31670
|
outputs: declaration.outputs ?? {},
|
|
31407
31671
|
host: convertHostDeclarationToMetadata(declaration.host),
|
|
31408
31672
|
queries: (declaration.queries ?? []).map(convertQueryDeclarationToMetadata),
|
|
@@ -31665,28 +31929,51 @@ function isInput(value) {
|
|
|
31665
31929
|
function isOutput(value) {
|
|
31666
31930
|
return value.ngMetadataName === 'Output';
|
|
31667
31931
|
}
|
|
31668
|
-
function
|
|
31669
|
-
return Object.keys(inputs).reduce((result,
|
|
31670
|
-
const value = inputs[
|
|
31671
|
-
|
|
31672
|
-
|
|
31673
|
-
|
|
31674
|
-
classPropertyName: value,
|
|
31675
|
-
transformFunction: null,
|
|
31676
|
-
required: false,
|
|
31677
|
-
};
|
|
31932
|
+
function inputsPartialMetadataToInputMetadata(inputs) {
|
|
31933
|
+
return Object.keys(inputs).reduce((result, minifiedClassName) => {
|
|
31934
|
+
const value = inputs[minifiedClassName];
|
|
31935
|
+
// Handle legacy partial input output.
|
|
31936
|
+
if (typeof value === 'string' || Array.isArray(value)) {
|
|
31937
|
+
result[minifiedClassName] = parseLegacyInputPartialOutput(value);
|
|
31678
31938
|
}
|
|
31679
31939
|
else {
|
|
31680
|
-
result[
|
|
31681
|
-
bindingPropertyName: value
|
|
31682
|
-
classPropertyName:
|
|
31683
|
-
transformFunction: value
|
|
31684
|
-
|
|
31940
|
+
result[minifiedClassName] = {
|
|
31941
|
+
bindingPropertyName: value.publicName,
|
|
31942
|
+
classPropertyName: minifiedClassName,
|
|
31943
|
+
transformFunction: value.transformFunction !== null ?
|
|
31944
|
+
new WrappedNodeExpr(value.transformFunction) :
|
|
31945
|
+
null,
|
|
31946
|
+
required: value.isRequired,
|
|
31947
|
+
isSignal: value.isSignal,
|
|
31685
31948
|
};
|
|
31686
31949
|
}
|
|
31687
31950
|
return result;
|
|
31688
31951
|
}, {});
|
|
31689
31952
|
}
|
|
31953
|
+
/**
|
|
31954
|
+
* Parses the legacy input partial output. For more details see `partial/directive.ts`.
|
|
31955
|
+
* TODO(legacy-partial-output-inputs): Remove in v18.
|
|
31956
|
+
*/
|
|
31957
|
+
function parseLegacyInputPartialOutput(value) {
|
|
31958
|
+
if (typeof value === 'string') {
|
|
31959
|
+
return {
|
|
31960
|
+
bindingPropertyName: value,
|
|
31961
|
+
classPropertyName: value,
|
|
31962
|
+
transformFunction: null,
|
|
31963
|
+
required: false,
|
|
31964
|
+
// legacy partial output does not capture signal inputs.
|
|
31965
|
+
isSignal: false,
|
|
31966
|
+
};
|
|
31967
|
+
}
|
|
31968
|
+
return {
|
|
31969
|
+
bindingPropertyName: value[0],
|
|
31970
|
+
classPropertyName: value[1],
|
|
31971
|
+
transformFunction: value[2] ? new WrappedNodeExpr(value[2]) : null,
|
|
31972
|
+
required: false,
|
|
31973
|
+
// legacy partial output does not capture signal inputs.
|
|
31974
|
+
isSignal: false,
|
|
31975
|
+
};
|
|
31976
|
+
}
|
|
31690
31977
|
function parseInputsArray(values) {
|
|
31691
31978
|
return values.reduce((results, value) => {
|
|
31692
31979
|
if (typeof value === 'string') {
|
|
@@ -31695,6 +31982,8 @@ function parseInputsArray(values) {
|
|
|
31695
31982
|
bindingPropertyName,
|
|
31696
31983
|
classPropertyName,
|
|
31697
31984
|
required: false,
|
|
31985
|
+
// Signal inputs not supported for the inputs array.
|
|
31986
|
+
isSignal: false,
|
|
31698
31987
|
transformFunction: null,
|
|
31699
31988
|
};
|
|
31700
31989
|
}
|
|
@@ -31703,6 +31992,8 @@ function parseInputsArray(values) {
|
|
|
31703
31992
|
bindingPropertyName: value.alias || value.name,
|
|
31704
31993
|
classPropertyName: value.name,
|
|
31705
31994
|
required: value.required || false,
|
|
31995
|
+
// Signal inputs not supported for the inputs array.
|
|
31996
|
+
isSignal: false,
|
|
31706
31997
|
transformFunction: value.transform != null ? new WrappedNodeExpr(value.transform) : null,
|
|
31707
31998
|
};
|
|
31708
31999
|
}
|
|
@@ -31755,7 +32046,7 @@ function publishFacade(global) {
|
|
|
31755
32046
|
* @description
|
|
31756
32047
|
* Entry point for all public APIs of the compiler package.
|
|
31757
32048
|
*/
|
|
31758
|
-
const VERSION = new Version('17.1.0-next.
|
|
32049
|
+
const VERSION = new Version('17.1.0-next.4');
|
|
31759
32050
|
|
|
31760
32051
|
class CompilerConfig {
|
|
31761
32052
|
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
@@ -33317,11 +33608,11 @@ function compileClassDebugInfo(debugInfo) {
|
|
|
33317
33608
|
*
|
|
33318
33609
|
* Do not include any prerelease in these versions as they are ignored.
|
|
33319
33610
|
*/
|
|
33320
|
-
const MINIMUM_PARTIAL_LINKER_VERSION$
|
|
33611
|
+
const MINIMUM_PARTIAL_LINKER_VERSION$5 = '12.0.0';
|
|
33321
33612
|
function compileDeclareClassMetadata(metadata) {
|
|
33322
33613
|
const definitionMap = new DefinitionMap();
|
|
33323
|
-
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$
|
|
33324
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
33614
|
+
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
|
|
33615
|
+
definitionMap.set('version', literal('17.1.0-next.4'));
|
|
33325
33616
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33326
33617
|
definitionMap.set('type', metadata.type);
|
|
33327
33618
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -33400,14 +33691,6 @@ function compileDependency(dep) {
|
|
|
33400
33691
|
return depMeta.toLiteralMap();
|
|
33401
33692
|
}
|
|
33402
33693
|
|
|
33403
|
-
/**
|
|
33404
|
-
* Every time we make a breaking change to the declaration interface or partial-linker behavior, we
|
|
33405
|
-
* must update this constant to prevent old partial-linkers from incorrectly processing the
|
|
33406
|
-
* declaration.
|
|
33407
|
-
*
|
|
33408
|
-
* Do not include any prerelease in these versions as they are ignored.
|
|
33409
|
-
*/
|
|
33410
|
-
const MINIMUM_PARTIAL_LINKER_VERSION$5 = '16.1.0';
|
|
33411
33694
|
/**
|
|
33412
33695
|
* Compile a directive declaration defined by the `R3DirectiveMetadata`.
|
|
33413
33696
|
*/
|
|
@@ -33423,13 +33706,9 @@ function compileDeclareDirectiveFromMetadata(meta) {
|
|
|
33423
33706
|
*/
|
|
33424
33707
|
function createDirectiveDefinitionMap(meta) {
|
|
33425
33708
|
const definitionMap = new DefinitionMap();
|
|
33426
|
-
const
|
|
33427
|
-
// Note: in order to allow consuming Angular libraries that have been compiled with 16.1+ in
|
|
33428
|
-
// Angular 16.0, we only force a minimum version of 16.1 if input transform feature as introduced
|
|
33429
|
-
// in 16.1 is actually used.
|
|
33430
|
-
const minVersion = hasTransformFunctions ? MINIMUM_PARTIAL_LINKER_VERSION$5 : '14.0.0';
|
|
33709
|
+
const minVersion = getMinimumVersionForPartialOutput(meta);
|
|
33431
33710
|
definitionMap.set('minVersion', literal(minVersion));
|
|
33432
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
33711
|
+
definitionMap.set('version', literal('17.1.0-next.4'));
|
|
33433
33712
|
// e.g. `type: MyDirective`
|
|
33434
33713
|
definitionMap.set('type', meta.type.value);
|
|
33435
33714
|
if (meta.isStandalone) {
|
|
@@ -33442,7 +33721,8 @@ function createDirectiveDefinitionMap(meta) {
|
|
|
33442
33721
|
if (meta.selector !== null) {
|
|
33443
33722
|
definitionMap.set('selector', literal(meta.selector));
|
|
33444
33723
|
}
|
|
33445
|
-
definitionMap.set('inputs',
|
|
33724
|
+
definitionMap.set('inputs', needsNewInputPartialOutput(meta) ? createInputsPartialMetadata(meta.inputs) :
|
|
33725
|
+
legacyInputsPartialMetadata(meta.inputs));
|
|
33446
33726
|
definitionMap.set('outputs', conditionallyCreateDirectiveBindingLiteral(meta.outputs));
|
|
33447
33727
|
definitionMap.set('host', compileHostMetadata(meta.host));
|
|
33448
33728
|
definitionMap.set('providers', meta.providers);
|
|
@@ -33467,6 +33747,44 @@ function createDirectiveDefinitionMap(meta) {
|
|
|
33467
33747
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33468
33748
|
return definitionMap;
|
|
33469
33749
|
}
|
|
33750
|
+
/**
|
|
33751
|
+
* Determines the minimum linker version for the partial output
|
|
33752
|
+
* generated for this directive.
|
|
33753
|
+
*
|
|
33754
|
+
* Every time we make a breaking change to the declaration interface or partial-linker
|
|
33755
|
+
* behavior, we must update the minimum versions to prevent old partial-linkers from
|
|
33756
|
+
* incorrectly processing the declaration.
|
|
33757
|
+
*
|
|
33758
|
+
* NOTE: Do not include any prerelease in these versions as they are ignored.
|
|
33759
|
+
*/
|
|
33760
|
+
function getMinimumVersionForPartialOutput(meta) {
|
|
33761
|
+
// We are starting with the oldest minimum version that can work for common
|
|
33762
|
+
// directive partial compilation output. As we discover usages of new features
|
|
33763
|
+
// that require a newer partial output emit, we bump the `minVersion`. Our goal
|
|
33764
|
+
// is to keep libraries as much compatible with older linker versions as possible.
|
|
33765
|
+
let minVersion = '14.0.0';
|
|
33766
|
+
// Note: in order to allow consuming Angular libraries that have been compiled with 16.1+ in
|
|
33767
|
+
// Angular 16.0, we only force a minimum version of 16.1 if input transform feature as introduced
|
|
33768
|
+
// in 16.1 is actually used.
|
|
33769
|
+
const hasTransformFunctions = Object.values(meta.inputs).some(input => input.transformFunction !== null);
|
|
33770
|
+
if (hasTransformFunctions) {
|
|
33771
|
+
minVersion = '16.1.0';
|
|
33772
|
+
}
|
|
33773
|
+
// If there are input flags and we need the new emit, use the actual minimum version,
|
|
33774
|
+
// where this was introduced. i.e. in 17.1.0
|
|
33775
|
+
// TODO(legacy-partial-output-inputs): Remove in v18.
|
|
33776
|
+
if (needsNewInputPartialOutput(meta)) {
|
|
33777
|
+
minVersion = '17.1.0';
|
|
33778
|
+
}
|
|
33779
|
+
return minVersion;
|
|
33780
|
+
}
|
|
33781
|
+
/**
|
|
33782
|
+
* Gets whether the given directive needs the new input partial output structure
|
|
33783
|
+
* that can hold additional metadata like `isRequired`, `isSignal` etc.
|
|
33784
|
+
*/
|
|
33785
|
+
function needsNewInputPartialOutput(meta) {
|
|
33786
|
+
return Object.values(meta.inputs).some(input => input.isSignal);
|
|
33787
|
+
}
|
|
33470
33788
|
/**
|
|
33471
33789
|
* Compiles the metadata of a single query into its partial declaration form as declared
|
|
33472
33790
|
* by `R3DeclareQueryMetadata`.
|
|
@@ -33540,6 +33858,74 @@ function createHostDirectives(hostDirectives) {
|
|
|
33540
33858
|
// otherwise we can save some bytes by using a plain array, e.g. `[{directive: HostDir}]`.
|
|
33541
33859
|
return literalArr(expressions);
|
|
33542
33860
|
}
|
|
33861
|
+
/**
|
|
33862
|
+
* Generates partial output metadata for inputs of a directive.
|
|
33863
|
+
*
|
|
33864
|
+
* The generated structure is expected to match `R3DeclareDirectiveFacade['inputs']`.
|
|
33865
|
+
*/
|
|
33866
|
+
function createInputsPartialMetadata(inputs) {
|
|
33867
|
+
const keys = Object.getOwnPropertyNames(inputs);
|
|
33868
|
+
if (keys.length === 0) {
|
|
33869
|
+
return null;
|
|
33870
|
+
}
|
|
33871
|
+
return literalMap(keys.map(declaredName => {
|
|
33872
|
+
const value = inputs[declaredName];
|
|
33873
|
+
return {
|
|
33874
|
+
key: declaredName,
|
|
33875
|
+
// put quotes around keys that contain potentially unsafe characters
|
|
33876
|
+
quoted: UNSAFE_OBJECT_KEY_NAME_REGEXP.test(declaredName),
|
|
33877
|
+
value: literalMap([
|
|
33878
|
+
{ key: 'classPropertyName', quoted: false, value: asLiteral(value.classPropertyName) },
|
|
33879
|
+
{ key: 'publicName', quoted: false, value: asLiteral(value.bindingPropertyName) },
|
|
33880
|
+
{ key: 'isSignal', quoted: false, value: asLiteral(value.isSignal) },
|
|
33881
|
+
{ key: 'isRequired', quoted: false, value: asLiteral(value.required) },
|
|
33882
|
+
{ key: 'transformFunction', quoted: false, value: value.transformFunction ?? NULL_EXPR },
|
|
33883
|
+
])
|
|
33884
|
+
};
|
|
33885
|
+
}));
|
|
33886
|
+
}
|
|
33887
|
+
/**
|
|
33888
|
+
* Pre v18 legacy partial output for inputs.
|
|
33889
|
+
*
|
|
33890
|
+
* Previously, inputs did not capture metadata like `isSignal` in the partial compilation output.
|
|
33891
|
+
* To enable capturing such metadata, we restructured how input metadata is communicated in the
|
|
33892
|
+
* partial output. This would make libraries incompatible with older Angular FW versions where the
|
|
33893
|
+
* linker would not know how to handle this new "format". For this reason, if we know this metadata
|
|
33894
|
+
* does not need to be captured- we fall back to the old format. This is what this function
|
|
33895
|
+
* generates.
|
|
33896
|
+
*
|
|
33897
|
+
* See:
|
|
33898
|
+
* https://github.com/angular/angular/blob/d4b423690210872b5c32a322a6090beda30b05a3/packages/core/src/compiler/compiler_facade_interface.ts#L197-L199
|
|
33899
|
+
*/
|
|
33900
|
+
function legacyInputsPartialMetadata(inputs) {
|
|
33901
|
+
// TODO(legacy-partial-output-inputs): Remove function in v18.
|
|
33902
|
+
const keys = Object.getOwnPropertyNames(inputs);
|
|
33903
|
+
if (keys.length === 0) {
|
|
33904
|
+
return null;
|
|
33905
|
+
}
|
|
33906
|
+
return literalMap(keys.map(declaredName => {
|
|
33907
|
+
const value = inputs[declaredName];
|
|
33908
|
+
const publicName = value.bindingPropertyName;
|
|
33909
|
+
const differentDeclaringName = publicName !== declaredName;
|
|
33910
|
+
let result;
|
|
33911
|
+
if (differentDeclaringName || value.transformFunction !== null) {
|
|
33912
|
+
const values = [asLiteral(publicName), asLiteral(declaredName)];
|
|
33913
|
+
if (value.transformFunction !== null) {
|
|
33914
|
+
values.push(value.transformFunction);
|
|
33915
|
+
}
|
|
33916
|
+
result = literalArr(values);
|
|
33917
|
+
}
|
|
33918
|
+
else {
|
|
33919
|
+
result = asLiteral(publicName);
|
|
33920
|
+
}
|
|
33921
|
+
return {
|
|
33922
|
+
key: declaredName,
|
|
33923
|
+
// put quotes around keys that contain potentially unsafe characters
|
|
33924
|
+
quoted: UNSAFE_OBJECT_KEY_NAME_REGEXP.test(declaredName),
|
|
33925
|
+
value: result,
|
|
33926
|
+
};
|
|
33927
|
+
}));
|
|
33928
|
+
}
|
|
33543
33929
|
|
|
33544
33930
|
/**
|
|
33545
33931
|
* Compile a component declaration defined by the `R3ComponentMetadata`.
|
|
@@ -33706,7 +34092,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
33706
34092
|
function compileDeclareFactoryFunction(meta) {
|
|
33707
34093
|
const definitionMap = new DefinitionMap();
|
|
33708
34094
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
33709
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
34095
|
+
definitionMap.set('version', literal('17.1.0-next.4'));
|
|
33710
34096
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33711
34097
|
definitionMap.set('type', meta.type.value);
|
|
33712
34098
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -33741,7 +34127,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
33741
34127
|
function createInjectableDefinitionMap(meta) {
|
|
33742
34128
|
const definitionMap = new DefinitionMap();
|
|
33743
34129
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
33744
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
34130
|
+
definitionMap.set('version', literal('17.1.0-next.4'));
|
|
33745
34131
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33746
34132
|
definitionMap.set('type', meta.type.value);
|
|
33747
34133
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -33792,7 +34178,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
33792
34178
|
function createInjectorDefinitionMap(meta) {
|
|
33793
34179
|
const definitionMap = new DefinitionMap();
|
|
33794
34180
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
33795
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
34181
|
+
definitionMap.set('version', literal('17.1.0-next.4'));
|
|
33796
34182
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33797
34183
|
definitionMap.set('type', meta.type.value);
|
|
33798
34184
|
definitionMap.set('providers', meta.providers);
|
|
@@ -33825,7 +34211,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
33825
34211
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
33826
34212
|
}
|
|
33827
34213
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
33828
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
34214
|
+
definitionMap.set('version', literal('17.1.0-next.4'));
|
|
33829
34215
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33830
34216
|
definitionMap.set('type', meta.type.value);
|
|
33831
34217
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -33876,7 +34262,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
33876
34262
|
function createPipeDefinitionMap(meta) {
|
|
33877
34263
|
const definitionMap = new DefinitionMap();
|
|
33878
34264
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
33879
|
-
definitionMap.set('version', literal('17.1.0-next.
|
|
34265
|
+
definitionMap.set('version', literal('17.1.0-next.4'));
|
|
33880
34266
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33881
34267
|
// e.g. `type: MyPipe`
|
|
33882
34268
|
definitionMap.set('type', meta.type.value);
|
|
@@ -33909,5 +34295,5 @@ publishFacade(_global);
|
|
|
33909
34295
|
|
|
33910
34296
|
// This file is not used to build this module. It is only used during editing
|
|
33911
34297
|
|
|
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 };
|
|
34298
|
+
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, encapsulateStyle, 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 };
|
|
33913
34299
|
//# sourceMappingURL=compiler.mjs.map
|