@angular-eslint/bundled-angular-compiler 16.1.2-alpha.8 → 16.1.2
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/dist/index.js +1873 -258
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @license Angular v16.
|
|
4
|
+
* @license Angular v16.2.3
|
|
5
5
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
6
6
|
* License: MIT
|
|
7
7
|
*/
|
|
@@ -1224,6 +1224,9 @@ class ReadVarExpr extends Expression {
|
|
|
1224
1224
|
visitExpression(visitor, context) {
|
|
1225
1225
|
return visitor.visitReadVarExpr(this, context);
|
|
1226
1226
|
}
|
|
1227
|
+
clone() {
|
|
1228
|
+
return new ReadVarExpr(this.name, this.type, this.sourceSpan);
|
|
1229
|
+
}
|
|
1227
1230
|
set(value) {
|
|
1228
1231
|
return new WriteVarExpr(this.name, value, null, this.sourceSpan);
|
|
1229
1232
|
}
|
|
@@ -1242,6 +1245,9 @@ class TypeofExpr extends Expression {
|
|
|
1242
1245
|
isConstant() {
|
|
1243
1246
|
return this.expr.isConstant();
|
|
1244
1247
|
}
|
|
1248
|
+
clone() {
|
|
1249
|
+
return new TypeofExpr(this.expr.clone());
|
|
1250
|
+
}
|
|
1245
1251
|
}
|
|
1246
1252
|
class WrappedNodeExpr extends Expression {
|
|
1247
1253
|
constructor(node, type, sourceSpan) {
|
|
@@ -1257,6 +1263,9 @@ class WrappedNodeExpr extends Expression {
|
|
|
1257
1263
|
visitExpression(visitor, context) {
|
|
1258
1264
|
return visitor.visitWrappedNodeExpr(this, context);
|
|
1259
1265
|
}
|
|
1266
|
+
clone() {
|
|
1267
|
+
return new WrappedNodeExpr(this.node, this.type, this.sourceSpan);
|
|
1268
|
+
}
|
|
1260
1269
|
}
|
|
1261
1270
|
class WriteVarExpr extends Expression {
|
|
1262
1271
|
constructor(name, value, type, sourceSpan) {
|
|
@@ -1273,6 +1282,9 @@ class WriteVarExpr extends Expression {
|
|
|
1273
1282
|
visitExpression(visitor, context) {
|
|
1274
1283
|
return visitor.visitWriteVarExpr(this, context);
|
|
1275
1284
|
}
|
|
1285
|
+
clone() {
|
|
1286
|
+
return new WriteVarExpr(this.name, this.value.clone(), this.type, this.sourceSpan);
|
|
1287
|
+
}
|
|
1276
1288
|
toDeclStmt(type, modifiers) {
|
|
1277
1289
|
return new DeclareVarStmt(this.name, this.value, type, modifiers, this.sourceSpan);
|
|
1278
1290
|
}
|
|
@@ -1297,6 +1309,9 @@ class WriteKeyExpr extends Expression {
|
|
|
1297
1309
|
visitExpression(visitor, context) {
|
|
1298
1310
|
return visitor.visitWriteKeyExpr(this, context);
|
|
1299
1311
|
}
|
|
1312
|
+
clone() {
|
|
1313
|
+
return new WriteKeyExpr(this.receiver.clone(), this.index.clone(), this.value.clone(), this.type, this.sourceSpan);
|
|
1314
|
+
}
|
|
1300
1315
|
}
|
|
1301
1316
|
class WritePropExpr extends Expression {
|
|
1302
1317
|
constructor(receiver, name, value, type, sourceSpan) {
|
|
@@ -1315,6 +1330,9 @@ class WritePropExpr extends Expression {
|
|
|
1315
1330
|
visitExpression(visitor, context) {
|
|
1316
1331
|
return visitor.visitWritePropExpr(this, context);
|
|
1317
1332
|
}
|
|
1333
|
+
clone() {
|
|
1334
|
+
return new WritePropExpr(this.receiver.clone(), this.name, this.value.clone(), this.type, this.sourceSpan);
|
|
1335
|
+
}
|
|
1318
1336
|
}
|
|
1319
1337
|
class InvokeFunctionExpr extends Expression {
|
|
1320
1338
|
constructor(fn, args, type, sourceSpan, pure = false) {
|
|
@@ -1323,6 +1341,10 @@ class InvokeFunctionExpr extends Expression {
|
|
|
1323
1341
|
this.args = args;
|
|
1324
1342
|
this.pure = pure;
|
|
1325
1343
|
}
|
|
1344
|
+
// An alias for fn, which allows other logic to handle calls and property reads together.
|
|
1345
|
+
get receiver() {
|
|
1346
|
+
return this.fn;
|
|
1347
|
+
}
|
|
1326
1348
|
isEquivalent(e) {
|
|
1327
1349
|
return e instanceof InvokeFunctionExpr && this.fn.isEquivalent(e.fn) &&
|
|
1328
1350
|
areAllEquivalent(this.args, e.args) && this.pure === e.pure;
|
|
@@ -1333,6 +1355,9 @@ class InvokeFunctionExpr extends Expression {
|
|
|
1333
1355
|
visitExpression(visitor, context) {
|
|
1334
1356
|
return visitor.visitInvokeFunctionExpr(this, context);
|
|
1335
1357
|
}
|
|
1358
|
+
clone() {
|
|
1359
|
+
return new InvokeFunctionExpr(this.fn.clone(), this.args.map(arg => arg.clone()), this.type, this.sourceSpan, this.pure);
|
|
1360
|
+
}
|
|
1336
1361
|
}
|
|
1337
1362
|
class TaggedTemplateExpr extends Expression {
|
|
1338
1363
|
constructor(tag, template, type, sourceSpan) {
|
|
@@ -1351,6 +1376,9 @@ class TaggedTemplateExpr extends Expression {
|
|
|
1351
1376
|
visitExpression(visitor, context) {
|
|
1352
1377
|
return visitor.visitTaggedTemplateExpr(this, context);
|
|
1353
1378
|
}
|
|
1379
|
+
clone() {
|
|
1380
|
+
return new TaggedTemplateExpr(this.tag.clone(), this.template.clone(), this.type, this.sourceSpan);
|
|
1381
|
+
}
|
|
1354
1382
|
}
|
|
1355
1383
|
class InstantiateExpr extends Expression {
|
|
1356
1384
|
constructor(classExpr, args, type, sourceSpan) {
|
|
@@ -1368,6 +1396,9 @@ class InstantiateExpr extends Expression {
|
|
|
1368
1396
|
visitExpression(visitor, context) {
|
|
1369
1397
|
return visitor.visitInstantiateExpr(this, context);
|
|
1370
1398
|
}
|
|
1399
|
+
clone() {
|
|
1400
|
+
return new InstantiateExpr(this.classExpr.clone(), this.args.map(arg => arg.clone()), this.type, this.sourceSpan);
|
|
1401
|
+
}
|
|
1371
1402
|
}
|
|
1372
1403
|
class LiteralExpr extends Expression {
|
|
1373
1404
|
constructor(value, type, sourceSpan) {
|
|
@@ -1383,12 +1414,18 @@ class LiteralExpr extends Expression {
|
|
|
1383
1414
|
visitExpression(visitor, context) {
|
|
1384
1415
|
return visitor.visitLiteralExpr(this, context);
|
|
1385
1416
|
}
|
|
1417
|
+
clone() {
|
|
1418
|
+
return new LiteralExpr(this.value, this.type, this.sourceSpan);
|
|
1419
|
+
}
|
|
1386
1420
|
}
|
|
1387
1421
|
class TemplateLiteral {
|
|
1388
1422
|
constructor(elements, expressions) {
|
|
1389
1423
|
this.elements = elements;
|
|
1390
1424
|
this.expressions = expressions;
|
|
1391
1425
|
}
|
|
1426
|
+
clone() {
|
|
1427
|
+
return new TemplateLiteral(this.elements.map(el => el.clone()), this.expressions.map(expr => expr.clone()));
|
|
1428
|
+
}
|
|
1392
1429
|
}
|
|
1393
1430
|
class TemplateLiteralElement {
|
|
1394
1431
|
constructor(text, sourceSpan, rawText) {
|
|
@@ -1403,6 +1440,9 @@ class TemplateLiteralElement {
|
|
|
1403
1440
|
this.rawText =
|
|
1404
1441
|
rawText ?? sourceSpan?.toString() ?? escapeForTemplateLiteral(escapeSlashes(text));
|
|
1405
1442
|
}
|
|
1443
|
+
clone() {
|
|
1444
|
+
return new TemplateLiteralElement(this.text, this.sourceSpan, this.rawText);
|
|
1445
|
+
}
|
|
1406
1446
|
}
|
|
1407
1447
|
class LiteralPiece {
|
|
1408
1448
|
constructor(text, sourceSpan) {
|
|
@@ -1447,6 +1487,9 @@ class LocalizedString extends Expression {
|
|
|
1447
1487
|
visitExpression(visitor, context) {
|
|
1448
1488
|
return visitor.visitLocalizedString(this, context);
|
|
1449
1489
|
}
|
|
1490
|
+
clone() {
|
|
1491
|
+
return new LocalizedString(this.metaBlock, this.messageParts, this.placeHolderNames, this.expressions.map(expr => expr.clone()), this.sourceSpan);
|
|
1492
|
+
}
|
|
1450
1493
|
/**
|
|
1451
1494
|
* Serialize the given `meta` and `messagePart` into "cooked" and "raw" strings that can be used
|
|
1452
1495
|
* in a `$localize` tagged string. The format of the metadata is the same as that parsed by
|
|
@@ -1548,6 +1591,9 @@ class ExternalExpr extends Expression {
|
|
|
1548
1591
|
visitExpression(visitor, context) {
|
|
1549
1592
|
return visitor.visitExternalExpr(this, context);
|
|
1550
1593
|
}
|
|
1594
|
+
clone() {
|
|
1595
|
+
return new ExternalExpr(this.value, this.type, this.typeParams, this.sourceSpan);
|
|
1596
|
+
}
|
|
1551
1597
|
}
|
|
1552
1598
|
class ExternalReference {
|
|
1553
1599
|
constructor(moduleName, name, runtime) {
|
|
@@ -1573,6 +1619,27 @@ class ConditionalExpr extends Expression {
|
|
|
1573
1619
|
visitExpression(visitor, context) {
|
|
1574
1620
|
return visitor.visitConditionalExpr(this, context);
|
|
1575
1621
|
}
|
|
1622
|
+
clone() {
|
|
1623
|
+
return new ConditionalExpr(this.condition.clone(), this.trueCase.clone(), this.falseCase?.clone(), this.type, this.sourceSpan);
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
class DynamicImportExpr extends Expression {
|
|
1627
|
+
constructor(url, sourceSpan) {
|
|
1628
|
+
super(null, sourceSpan);
|
|
1629
|
+
this.url = url;
|
|
1630
|
+
}
|
|
1631
|
+
isEquivalent(e) {
|
|
1632
|
+
return e instanceof DynamicImportExpr && this.url === e.url;
|
|
1633
|
+
}
|
|
1634
|
+
isConstant() {
|
|
1635
|
+
return false;
|
|
1636
|
+
}
|
|
1637
|
+
visitExpression(visitor, context) {
|
|
1638
|
+
return visitor.visitDynamicImportExpr(this, context);
|
|
1639
|
+
}
|
|
1640
|
+
clone() {
|
|
1641
|
+
return new DynamicImportExpr(this.url, this.sourceSpan);
|
|
1642
|
+
}
|
|
1576
1643
|
}
|
|
1577
1644
|
class NotExpr extends Expression {
|
|
1578
1645
|
constructor(condition, sourceSpan) {
|
|
@@ -1588,6 +1655,9 @@ class NotExpr extends Expression {
|
|
|
1588
1655
|
visitExpression(visitor, context) {
|
|
1589
1656
|
return visitor.visitNotExpr(this, context);
|
|
1590
1657
|
}
|
|
1658
|
+
clone() {
|
|
1659
|
+
return new NotExpr(this.condition.clone(), this.sourceSpan);
|
|
1660
|
+
}
|
|
1591
1661
|
}
|
|
1592
1662
|
class FnParam {
|
|
1593
1663
|
constructor(name, type = null) {
|
|
@@ -1597,6 +1667,9 @@ class FnParam {
|
|
|
1597
1667
|
isEquivalent(param) {
|
|
1598
1668
|
return this.name === param.name;
|
|
1599
1669
|
}
|
|
1670
|
+
clone() {
|
|
1671
|
+
return new FnParam(this.name, this.type);
|
|
1672
|
+
}
|
|
1600
1673
|
}
|
|
1601
1674
|
class FunctionExpr extends Expression {
|
|
1602
1675
|
constructor(params, statements, type, sourceSpan, name) {
|
|
@@ -1618,6 +1691,10 @@ class FunctionExpr extends Expression {
|
|
|
1618
1691
|
toDeclStmt(name, modifiers) {
|
|
1619
1692
|
return new DeclareFunctionStmt(name, this.params, this.statements, this.type, modifiers, this.sourceSpan);
|
|
1620
1693
|
}
|
|
1694
|
+
clone() {
|
|
1695
|
+
// TODO: Should we deep clone statements?
|
|
1696
|
+
return new FunctionExpr(this.params.map(p => p.clone()), this.statements, this.type, this.sourceSpan, this.name);
|
|
1697
|
+
}
|
|
1621
1698
|
}
|
|
1622
1699
|
class UnaryOperatorExpr extends Expression {
|
|
1623
1700
|
constructor(operator, expr, type, sourceSpan, parens = true) {
|
|
@@ -1636,6 +1713,9 @@ class UnaryOperatorExpr extends Expression {
|
|
|
1636
1713
|
visitExpression(visitor, context) {
|
|
1637
1714
|
return visitor.visitUnaryOperatorExpr(this, context);
|
|
1638
1715
|
}
|
|
1716
|
+
clone() {
|
|
1717
|
+
return new UnaryOperatorExpr(this.operator, this.expr.clone(), this.type, this.sourceSpan, this.parens);
|
|
1718
|
+
}
|
|
1639
1719
|
}
|
|
1640
1720
|
class BinaryOperatorExpr extends Expression {
|
|
1641
1721
|
constructor(operator, lhs, rhs, type, sourceSpan, parens = true) {
|
|
@@ -1655,6 +1735,9 @@ class BinaryOperatorExpr extends Expression {
|
|
|
1655
1735
|
visitExpression(visitor, context) {
|
|
1656
1736
|
return visitor.visitBinaryOperatorExpr(this, context);
|
|
1657
1737
|
}
|
|
1738
|
+
clone() {
|
|
1739
|
+
return new BinaryOperatorExpr(this.operator, this.lhs.clone(), this.rhs.clone(), this.type, this.sourceSpan, this.parens);
|
|
1740
|
+
}
|
|
1658
1741
|
}
|
|
1659
1742
|
class ReadPropExpr extends Expression {
|
|
1660
1743
|
constructor(receiver, name, type, sourceSpan) {
|
|
@@ -1662,6 +1745,10 @@ class ReadPropExpr extends Expression {
|
|
|
1662
1745
|
this.receiver = receiver;
|
|
1663
1746
|
this.name = name;
|
|
1664
1747
|
}
|
|
1748
|
+
// An alias for name, which allows other logic to handle property reads and keyed reads together.
|
|
1749
|
+
get index() {
|
|
1750
|
+
return this.name;
|
|
1751
|
+
}
|
|
1665
1752
|
isEquivalent(e) {
|
|
1666
1753
|
return e instanceof ReadPropExpr && this.receiver.isEquivalent(e.receiver) &&
|
|
1667
1754
|
this.name === e.name;
|
|
@@ -1675,6 +1762,9 @@ class ReadPropExpr extends Expression {
|
|
|
1675
1762
|
set(value) {
|
|
1676
1763
|
return new WritePropExpr(this.receiver, this.name, value, null, this.sourceSpan);
|
|
1677
1764
|
}
|
|
1765
|
+
clone() {
|
|
1766
|
+
return new ReadPropExpr(this.receiver.clone(), this.name, this.type, this.sourceSpan);
|
|
1767
|
+
}
|
|
1678
1768
|
}
|
|
1679
1769
|
class ReadKeyExpr extends Expression {
|
|
1680
1770
|
constructor(receiver, index, type, sourceSpan) {
|
|
@@ -1695,6 +1785,9 @@ class ReadKeyExpr extends Expression {
|
|
|
1695
1785
|
set(value) {
|
|
1696
1786
|
return new WriteKeyExpr(this.receiver, this.index, value, null, this.sourceSpan);
|
|
1697
1787
|
}
|
|
1788
|
+
clone() {
|
|
1789
|
+
return new ReadKeyExpr(this.receiver.clone(), this.index.clone(), this.type, this.sourceSpan);
|
|
1790
|
+
}
|
|
1698
1791
|
}
|
|
1699
1792
|
class LiteralArrayExpr extends Expression {
|
|
1700
1793
|
constructor(entries, type, sourceSpan) {
|
|
@@ -1710,6 +1803,9 @@ class LiteralArrayExpr extends Expression {
|
|
|
1710
1803
|
visitExpression(visitor, context) {
|
|
1711
1804
|
return visitor.visitLiteralArrayExpr(this, context);
|
|
1712
1805
|
}
|
|
1806
|
+
clone() {
|
|
1807
|
+
return new LiteralArrayExpr(this.entries.map(e => e.clone()), this.type, this.sourceSpan);
|
|
1808
|
+
}
|
|
1713
1809
|
}
|
|
1714
1810
|
class LiteralMapEntry {
|
|
1715
1811
|
constructor(key, value, quoted) {
|
|
@@ -1720,6 +1816,9 @@ class LiteralMapEntry {
|
|
|
1720
1816
|
isEquivalent(e) {
|
|
1721
1817
|
return this.key === e.key && this.value.isEquivalent(e.value);
|
|
1722
1818
|
}
|
|
1819
|
+
clone() {
|
|
1820
|
+
return new LiteralMapEntry(this.key, this.value.clone(), this.quoted);
|
|
1821
|
+
}
|
|
1723
1822
|
}
|
|
1724
1823
|
class LiteralMapExpr extends Expression {
|
|
1725
1824
|
constructor(entries, type, sourceSpan) {
|
|
@@ -1739,6 +1838,10 @@ class LiteralMapExpr extends Expression {
|
|
|
1739
1838
|
visitExpression(visitor, context) {
|
|
1740
1839
|
return visitor.visitLiteralMapExpr(this, context);
|
|
1741
1840
|
}
|
|
1841
|
+
clone() {
|
|
1842
|
+
const entriesClone = this.entries.map(entry => entry.clone());
|
|
1843
|
+
return new LiteralMapExpr(entriesClone, this.type, this.sourceSpan);
|
|
1844
|
+
}
|
|
1742
1845
|
}
|
|
1743
1846
|
class CommaExpr extends Expression {
|
|
1744
1847
|
constructor(parts, sourceSpan) {
|
|
@@ -1754,6 +1857,9 @@ class CommaExpr extends Expression {
|
|
|
1754
1857
|
visitExpression(visitor, context) {
|
|
1755
1858
|
return visitor.visitCommaExpr(this, context);
|
|
1756
1859
|
}
|
|
1860
|
+
clone() {
|
|
1861
|
+
return new CommaExpr(this.parts.map(p => p.clone()));
|
|
1862
|
+
}
|
|
1757
1863
|
}
|
|
1758
1864
|
const NULL_EXPR = new LiteralExpr(null, null, null);
|
|
1759
1865
|
const TYPED_NULL_EXPR = new LiteralExpr(null, INFERRED_TYPE, null);
|
|
@@ -1923,6 +2029,9 @@ class RecursiveAstVisitor$1 {
|
|
|
1923
2029
|
ast.value.visitExpression(this, context);
|
|
1924
2030
|
return this.visitExpression(ast, context);
|
|
1925
2031
|
}
|
|
2032
|
+
visitDynamicImportExpr(ast, context) {
|
|
2033
|
+
return this.visitExpression(ast, context);
|
|
2034
|
+
}
|
|
1926
2035
|
visitInvokeFunctionExpr(ast, context) {
|
|
1927
2036
|
ast.fn.visitExpression(this, context);
|
|
1928
2037
|
this.visitAllExpressions(ast.args, context);
|
|
@@ -2161,6 +2270,7 @@ var output_ast = /*#__PURE__*/Object.freeze({
|
|
|
2161
2270
|
ExternalExpr: ExternalExpr,
|
|
2162
2271
|
ExternalReference: ExternalReference,
|
|
2163
2272
|
ConditionalExpr: ConditionalExpr,
|
|
2273
|
+
DynamicImportExpr: DynamicImportExpr,
|
|
2164
2274
|
NotExpr: NotExpr,
|
|
2165
2275
|
FnParam: FnParam,
|
|
2166
2276
|
FunctionExpr: FunctionExpr,
|
|
@@ -2258,6 +2368,9 @@ class FixupExpression extends Expression {
|
|
|
2258
2368
|
isConstant() {
|
|
2259
2369
|
return true;
|
|
2260
2370
|
}
|
|
2371
|
+
clone() {
|
|
2372
|
+
throw new Error(`Not supported.`);
|
|
2373
|
+
}
|
|
2261
2374
|
fixup(expression) {
|
|
2262
2375
|
this.resolved = expression;
|
|
2263
2376
|
this.shared = true;
|
|
@@ -2502,6 +2615,7 @@ class Identifiers {
|
|
|
2502
2615
|
static { this.nextContext = { name: 'ɵɵnextContext', moduleName: CORE }; }
|
|
2503
2616
|
static { this.resetView = { name: 'ɵɵresetView', moduleName: CORE }; }
|
|
2504
2617
|
static { this.templateCreate = { name: 'ɵɵtemplate', moduleName: CORE }; }
|
|
2618
|
+
static { this.defer = { name: 'ɵɵdefer', moduleName: CORE }; }
|
|
2505
2619
|
static { this.text = { name: 'ɵɵtext', moduleName: CORE }; }
|
|
2506
2620
|
static { this.enableBindings = { name: 'ɵɵenableBindings', moduleName: CORE }; }
|
|
2507
2621
|
static { this.disableBindings = { name: 'ɵɵdisableBindings', moduleName: CORE }; }
|
|
@@ -2732,13 +2846,7 @@ class Version {
|
|
|
2732
2846
|
this.patch = splits.slice(2).join('.');
|
|
2733
2847
|
}
|
|
2734
2848
|
}
|
|
2735
|
-
|
|
2736
|
-
// `_global` variable should point to the NodeJS `global` in that case. Note: Typeof/Instanceof
|
|
2737
|
-
// checks are considered side-effects in Terser. We explicitly mark this as side-effect free:
|
|
2738
|
-
// https://github.com/terser/terser/issues/250.
|
|
2739
|
-
const _global = ( /* @__PURE__ */(() => (typeof global !== 'undefined' && global) || (typeof window !== 'undefined' && window) ||
|
|
2740
|
-
(typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' &&
|
|
2741
|
-
self instanceof WorkerGlobalScope && self))());
|
|
2849
|
+
const _global = globalThis;
|
|
2742
2850
|
/**
|
|
2743
2851
|
* Partitions a given array into 2 arrays, based on a boolean value returned by the condition
|
|
2744
2852
|
* function.
|
|
@@ -3213,6 +3321,9 @@ class AbstractEmitterVisitor {
|
|
|
3213
3321
|
ctx.print(ast, `)`);
|
|
3214
3322
|
return null;
|
|
3215
3323
|
}
|
|
3324
|
+
visitDynamicImportExpr(ast, ctx) {
|
|
3325
|
+
ctx.print(ast, `import(${ast.url})`);
|
|
3326
|
+
}
|
|
3216
3327
|
visitNotExpr(ast, ctx) {
|
|
3217
3328
|
ctx.print(ast, '!');
|
|
3218
3329
|
ast.condition.visitExpression(this, ctx);
|
|
@@ -3786,6 +3897,96 @@ class Element$1 {
|
|
|
3786
3897
|
return visitor.visitElement(this);
|
|
3787
3898
|
}
|
|
3788
3899
|
}
|
|
3900
|
+
class DeferredTrigger {
|
|
3901
|
+
constructor(sourceSpan) {
|
|
3902
|
+
this.sourceSpan = sourceSpan;
|
|
3903
|
+
}
|
|
3904
|
+
visit(visitor) {
|
|
3905
|
+
return visitor.visitDeferredTrigger(this);
|
|
3906
|
+
}
|
|
3907
|
+
}
|
|
3908
|
+
class BoundDeferredTrigger extends DeferredTrigger {
|
|
3909
|
+
constructor(value, sourceSpan) {
|
|
3910
|
+
super(sourceSpan);
|
|
3911
|
+
this.value = value;
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
class IdleDeferredTrigger extends DeferredTrigger {
|
|
3915
|
+
}
|
|
3916
|
+
class ImmediateDeferredTrigger extends DeferredTrigger {
|
|
3917
|
+
}
|
|
3918
|
+
class HoverDeferredTrigger extends DeferredTrigger {
|
|
3919
|
+
}
|
|
3920
|
+
class TimerDeferredTrigger extends DeferredTrigger {
|
|
3921
|
+
constructor(delay, sourceSpan) {
|
|
3922
|
+
super(sourceSpan);
|
|
3923
|
+
this.delay = delay;
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
class InteractionDeferredTrigger extends DeferredTrigger {
|
|
3927
|
+
constructor(reference, sourceSpan) {
|
|
3928
|
+
super(sourceSpan);
|
|
3929
|
+
this.reference = reference;
|
|
3930
|
+
}
|
|
3931
|
+
}
|
|
3932
|
+
class ViewportDeferredTrigger extends DeferredTrigger {
|
|
3933
|
+
constructor(reference, sourceSpan) {
|
|
3934
|
+
super(sourceSpan);
|
|
3935
|
+
this.reference = reference;
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
class DeferredBlockPlaceholder {
|
|
3939
|
+
constructor(children, minimumTime, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3940
|
+
this.children = children;
|
|
3941
|
+
this.minimumTime = minimumTime;
|
|
3942
|
+
this.sourceSpan = sourceSpan;
|
|
3943
|
+
this.startSourceSpan = startSourceSpan;
|
|
3944
|
+
this.endSourceSpan = endSourceSpan;
|
|
3945
|
+
}
|
|
3946
|
+
visit(visitor) {
|
|
3947
|
+
return visitor.visitDeferredBlockPlaceholder(this);
|
|
3948
|
+
}
|
|
3949
|
+
}
|
|
3950
|
+
class DeferredBlockLoading {
|
|
3951
|
+
constructor(children, afterTime, minimumTime, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3952
|
+
this.children = children;
|
|
3953
|
+
this.afterTime = afterTime;
|
|
3954
|
+
this.minimumTime = minimumTime;
|
|
3955
|
+
this.sourceSpan = sourceSpan;
|
|
3956
|
+
this.startSourceSpan = startSourceSpan;
|
|
3957
|
+
this.endSourceSpan = endSourceSpan;
|
|
3958
|
+
}
|
|
3959
|
+
visit(visitor) {
|
|
3960
|
+
return visitor.visitDeferredBlockLoading(this);
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
class DeferredBlockError {
|
|
3964
|
+
constructor(children, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3965
|
+
this.children = children;
|
|
3966
|
+
this.sourceSpan = sourceSpan;
|
|
3967
|
+
this.startSourceSpan = startSourceSpan;
|
|
3968
|
+
this.endSourceSpan = endSourceSpan;
|
|
3969
|
+
}
|
|
3970
|
+
visit(visitor) {
|
|
3971
|
+
return visitor.visitDeferredBlockError(this);
|
|
3972
|
+
}
|
|
3973
|
+
}
|
|
3974
|
+
class DeferredBlock {
|
|
3975
|
+
constructor(children, triggers, prefetchTriggers, placeholder, loading, error, sourceSpan, startSourceSpan, endSourceSpan) {
|
|
3976
|
+
this.children = children;
|
|
3977
|
+
this.triggers = triggers;
|
|
3978
|
+
this.prefetchTriggers = prefetchTriggers;
|
|
3979
|
+
this.placeholder = placeholder;
|
|
3980
|
+
this.loading = loading;
|
|
3981
|
+
this.error = error;
|
|
3982
|
+
this.sourceSpan = sourceSpan;
|
|
3983
|
+
this.startSourceSpan = startSourceSpan;
|
|
3984
|
+
this.endSourceSpan = endSourceSpan;
|
|
3985
|
+
}
|
|
3986
|
+
visit(visitor) {
|
|
3987
|
+
return visitor.visitDeferredBlock(this);
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3789
3990
|
class Template {
|
|
3790
3991
|
constructor(
|
|
3791
3992
|
// tagName is the name of the container element, if applicable.
|
|
@@ -3873,6 +4074,23 @@ class RecursiveVisitor$1 {
|
|
|
3873
4074
|
visitAll$1(this, template.references);
|
|
3874
4075
|
visitAll$1(this, template.variables);
|
|
3875
4076
|
}
|
|
4077
|
+
visitDeferredBlock(deferred) {
|
|
4078
|
+
visitAll$1(this, deferred.triggers);
|
|
4079
|
+
visitAll$1(this, deferred.prefetchTriggers);
|
|
4080
|
+
visitAll$1(this, deferred.children);
|
|
4081
|
+
deferred.placeholder?.visit(this);
|
|
4082
|
+
deferred.loading?.visit(this);
|
|
4083
|
+
deferred.error?.visit(this);
|
|
4084
|
+
}
|
|
4085
|
+
visitDeferredBlockPlaceholder(block) {
|
|
4086
|
+
visitAll$1(this, block.children);
|
|
4087
|
+
}
|
|
4088
|
+
visitDeferredBlockError(block) {
|
|
4089
|
+
visitAll$1(this, block.children);
|
|
4090
|
+
}
|
|
4091
|
+
visitDeferredBlockLoading(block) {
|
|
4092
|
+
visitAll$1(this, block.children);
|
|
4093
|
+
}
|
|
3876
4094
|
visitContent(content) { }
|
|
3877
4095
|
visitVariable(variable) { }
|
|
3878
4096
|
visitReference(reference) { }
|
|
@@ -3882,6 +4100,7 @@ class RecursiveVisitor$1 {
|
|
|
3882
4100
|
visitText(text) { }
|
|
3883
4101
|
visitBoundText(text) { }
|
|
3884
4102
|
visitIcu(icu) { }
|
|
4103
|
+
visitDeferredTrigger(trigger) { }
|
|
3885
4104
|
}
|
|
3886
4105
|
function visitAll$1(visitor, nodes) {
|
|
3887
4106
|
const result = [];
|
|
@@ -5821,7 +6040,7 @@ class ASTWithName extends AST {
|
|
|
5821
6040
|
this.nameSpan = nameSpan;
|
|
5822
6041
|
}
|
|
5823
6042
|
}
|
|
5824
|
-
class EmptyExpr extends AST {
|
|
6043
|
+
class EmptyExpr$1 extends AST {
|
|
5825
6044
|
visit(visitor, context = null) {
|
|
5826
6045
|
// do nothing
|
|
5827
6046
|
}
|
|
@@ -5968,7 +6187,7 @@ class LiteralMap extends AST {
|
|
|
5968
6187
|
return visitor.visitLiteralMap(this, context);
|
|
5969
6188
|
}
|
|
5970
6189
|
}
|
|
5971
|
-
class Interpolation extends AST {
|
|
6190
|
+
class Interpolation$1 extends AST {
|
|
5972
6191
|
constructor(span, sourceSpan, strings, expressions) {
|
|
5973
6192
|
super(span, sourceSpan);
|
|
5974
6193
|
this.strings = strings;
|
|
@@ -6215,7 +6434,7 @@ class AstTransformer {
|
|
|
6215
6434
|
return ast;
|
|
6216
6435
|
}
|
|
6217
6436
|
visitInterpolation(ast, context) {
|
|
6218
|
-
return new Interpolation(ast.span, ast.sourceSpan, ast.strings, this.visitAll(ast.expressions));
|
|
6437
|
+
return new Interpolation$1(ast.span, ast.sourceSpan, ast.strings, this.visitAll(ast.expressions));
|
|
6219
6438
|
}
|
|
6220
6439
|
visitLiteralPrimitive(ast, context) {
|
|
6221
6440
|
return new LiteralPrimitive(ast.span, ast.sourceSpan, ast.value);
|
|
@@ -6298,7 +6517,7 @@ class AstMemoryEfficientTransformer {
|
|
|
6298
6517
|
visitInterpolation(ast, context) {
|
|
6299
6518
|
const expressions = this.visitAll(ast.expressions);
|
|
6300
6519
|
if (expressions !== ast.expressions)
|
|
6301
|
-
return new Interpolation(ast.span, ast.sourceSpan, ast.strings, expressions);
|
|
6520
|
+
return new Interpolation$1(ast.span, ast.sourceSpan, ast.strings, expressions);
|
|
6302
6521
|
return ast;
|
|
6303
6522
|
}
|
|
6304
6523
|
visitLiteralPrimitive(ast, context) {
|
|
@@ -7236,6 +7455,7 @@ class InterpolationExpression extends Expression {
|
|
|
7236
7455
|
this.isConstant = unsupported;
|
|
7237
7456
|
this.isEquivalent = unsupported;
|
|
7238
7457
|
this.visitExpression = unsupported;
|
|
7458
|
+
this.clone = unsupported;
|
|
7239
7459
|
}
|
|
7240
7460
|
}
|
|
7241
7461
|
class DefaultLocalResolver {
|
|
@@ -7253,7 +7473,7 @@ class DefaultLocalResolver {
|
|
|
7253
7473
|
}
|
|
7254
7474
|
class BuiltinFunctionCall extends Call {
|
|
7255
7475
|
constructor(span, sourceSpan, args, converter) {
|
|
7256
|
-
super(span, sourceSpan, new EmptyExpr(span, sourceSpan), args, null);
|
|
7476
|
+
super(span, sourceSpan, new EmptyExpr$1(span, sourceSpan), args, null);
|
|
7257
7477
|
this.converter = converter;
|
|
7258
7478
|
}
|
|
7259
7479
|
}
|
|
@@ -7851,7 +8071,7 @@ class ShadowCss {
|
|
|
7851
8071
|
}
|
|
7852
8072
|
else if (rule.selector.startsWith('@media') || rule.selector.startsWith('@supports') ||
|
|
7853
8073
|
rule.selector.startsWith('@document') || rule.selector.startsWith('@layer') ||
|
|
7854
|
-
rule.selector.startsWith('@container')) {
|
|
8074
|
+
rule.selector.startsWith('@container') || rule.selector.startsWith('@scope')) {
|
|
7855
8075
|
content = this._scopeSelectors(rule.content, scopeSelector, hostSelector);
|
|
7856
8076
|
}
|
|
7857
8077
|
else if (rule.selector.startsWith('@font-face') || rule.selector.startsWith('@page')) {
|
|
@@ -8380,33 +8600,37 @@ function mergeNsAndName(prefix, localName) {
|
|
|
8380
8600
|
/**
|
|
8381
8601
|
* Enumeration of the types of attributes which can be applied to an element.
|
|
8382
8602
|
*/
|
|
8383
|
-
var
|
|
8384
|
-
(function (
|
|
8603
|
+
var BindingKind;
|
|
8604
|
+
(function (BindingKind) {
|
|
8385
8605
|
/**
|
|
8386
8606
|
* Static attributes.
|
|
8387
8607
|
*/
|
|
8388
|
-
|
|
8608
|
+
BindingKind[BindingKind["Attribute"] = 0] = "Attribute";
|
|
8389
8609
|
/**
|
|
8390
8610
|
* Class bindings.
|
|
8391
8611
|
*/
|
|
8392
|
-
|
|
8612
|
+
BindingKind[BindingKind["ClassName"] = 1] = "ClassName";
|
|
8393
8613
|
/**
|
|
8394
8614
|
* Style bindings.
|
|
8395
8615
|
*/
|
|
8396
|
-
|
|
8616
|
+
BindingKind[BindingKind["StyleProperty"] = 2] = "StyleProperty";
|
|
8397
8617
|
/**
|
|
8398
|
-
* Dynamic property
|
|
8618
|
+
* Dynamic property bindings.
|
|
8399
8619
|
*/
|
|
8400
|
-
|
|
8620
|
+
BindingKind[BindingKind["Property"] = 3] = "Property";
|
|
8401
8621
|
/**
|
|
8402
|
-
*
|
|
8622
|
+
* Property or attribute bindings on a template.
|
|
8403
8623
|
*/
|
|
8404
|
-
|
|
8624
|
+
BindingKind[BindingKind["Template"] = 4] = "Template";
|
|
8405
8625
|
/**
|
|
8406
8626
|
* Internationalized attributes.
|
|
8407
8627
|
*/
|
|
8408
|
-
|
|
8409
|
-
|
|
8628
|
+
BindingKind[BindingKind["I18n"] = 5] = "I18n";
|
|
8629
|
+
/**
|
|
8630
|
+
* TODO: Consider how Animations are handled, and if they should be a distinct BindingKind.
|
|
8631
|
+
*/
|
|
8632
|
+
BindingKind[BindingKind["Animation"] = 6] = "Animation";
|
|
8633
|
+
})(BindingKind || (BindingKind = {}));
|
|
8410
8634
|
|
|
8411
8635
|
/**
|
|
8412
8636
|
* Distinguishes different kinds of IR operations.
|
|
@@ -8456,34 +8680,73 @@ var OpKind;
|
|
|
8456
8680
|
* An operation to end an `ng-container`.
|
|
8457
8681
|
*/
|
|
8458
8682
|
OpKind[OpKind["ContainerEnd"] = 9] = "ContainerEnd";
|
|
8683
|
+
/**
|
|
8684
|
+
* An operation disable binding for subsequent elements, which are descendants of a non-bindable
|
|
8685
|
+
* node.
|
|
8686
|
+
*/
|
|
8687
|
+
OpKind[OpKind["DisableBindings"] = 10] = "DisableBindings";
|
|
8688
|
+
/**
|
|
8689
|
+
* An operation to re-enable binding, after it was previously disabled.
|
|
8690
|
+
*/
|
|
8691
|
+
OpKind[OpKind["EnableBindings"] = 11] = "EnableBindings";
|
|
8459
8692
|
/**
|
|
8460
8693
|
* An operation to render a text node.
|
|
8461
8694
|
*/
|
|
8462
|
-
OpKind[OpKind["Text"] =
|
|
8695
|
+
OpKind[OpKind["Text"] = 12] = "Text";
|
|
8463
8696
|
/**
|
|
8464
8697
|
* An operation declaring an event listener for an element.
|
|
8465
8698
|
*/
|
|
8466
|
-
OpKind[OpKind["Listener"] =
|
|
8699
|
+
OpKind[OpKind["Listener"] = 13] = "Listener";
|
|
8467
8700
|
/**
|
|
8468
8701
|
* An operation to interpolate text into a text node.
|
|
8469
8702
|
*/
|
|
8470
|
-
OpKind[OpKind["InterpolateText"] =
|
|
8703
|
+
OpKind[OpKind["InterpolateText"] = 14] = "InterpolateText";
|
|
8704
|
+
/**
|
|
8705
|
+
* An intermediate binding op, that has not yet been processed into an individual property,
|
|
8706
|
+
* attribute, style, etc.
|
|
8707
|
+
*/
|
|
8708
|
+
OpKind[OpKind["Binding"] = 15] = "Binding";
|
|
8471
8709
|
/**
|
|
8472
8710
|
* An operation to bind an expression to a property of an element.
|
|
8473
8711
|
*/
|
|
8474
|
-
OpKind[OpKind["Property"] =
|
|
8712
|
+
OpKind[OpKind["Property"] = 16] = "Property";
|
|
8713
|
+
/**
|
|
8714
|
+
* An operation to bind an expression to a style property of an element.
|
|
8715
|
+
*/
|
|
8716
|
+
OpKind[OpKind["StyleProp"] = 17] = "StyleProp";
|
|
8475
8717
|
/**
|
|
8476
|
-
* An operation to
|
|
8718
|
+
* An operation to bind an expression to a class property of an element.
|
|
8477
8719
|
*/
|
|
8478
|
-
OpKind[OpKind["
|
|
8720
|
+
OpKind[OpKind["ClassProp"] = 18] = "ClassProp";
|
|
8721
|
+
/**
|
|
8722
|
+
* An operation to bind an expression to the styles of an element.
|
|
8723
|
+
*/
|
|
8724
|
+
OpKind[OpKind["StyleMap"] = 19] = "StyleMap";
|
|
8725
|
+
/**
|
|
8726
|
+
* An operation to bind an expression to the classes of an element.
|
|
8727
|
+
*/
|
|
8728
|
+
OpKind[OpKind["ClassMap"] = 20] = "ClassMap";
|
|
8479
8729
|
/**
|
|
8480
8730
|
* An operation to advance the runtime's implicit slot context during the update phase of a view.
|
|
8481
8731
|
*/
|
|
8482
|
-
OpKind[OpKind["Advance"] =
|
|
8732
|
+
OpKind[OpKind["Advance"] = 21] = "Advance";
|
|
8483
8733
|
/**
|
|
8484
8734
|
* An operation to instantiate a pipe.
|
|
8485
8735
|
*/
|
|
8486
|
-
OpKind[OpKind["Pipe"] =
|
|
8736
|
+
OpKind[OpKind["Pipe"] = 22] = "Pipe";
|
|
8737
|
+
/**
|
|
8738
|
+
* An operation to associate an attribute with an element.
|
|
8739
|
+
*/
|
|
8740
|
+
OpKind[OpKind["Attribute"] = 23] = "Attribute";
|
|
8741
|
+
/**
|
|
8742
|
+
* A host binding property.
|
|
8743
|
+
*/
|
|
8744
|
+
OpKind[OpKind["HostProperty"] = 24] = "HostProperty";
|
|
8745
|
+
/**
|
|
8746
|
+
* A namespace change, which causes the subsequent elements to be processed as either HTML or SVG.
|
|
8747
|
+
*/
|
|
8748
|
+
OpKind[OpKind["Namespace"] = 25] = "Namespace";
|
|
8749
|
+
// TODO: Add Host Listeners, and possibly other host ops also.
|
|
8487
8750
|
})(OpKind || (OpKind = {}));
|
|
8488
8751
|
/**
|
|
8489
8752
|
* Distinguishes different kinds of IR expressions.
|
|
@@ -8538,6 +8801,38 @@ var ExpressionKind;
|
|
|
8538
8801
|
* Binding to a pipe transformation with a variable number of arguments.
|
|
8539
8802
|
*/
|
|
8540
8803
|
ExpressionKind[ExpressionKind["PipeBindingVariadic"] = 11] = "PipeBindingVariadic";
|
|
8804
|
+
/*
|
|
8805
|
+
* A safe property read requiring expansion into a null check.
|
|
8806
|
+
*/
|
|
8807
|
+
ExpressionKind[ExpressionKind["SafePropertyRead"] = 12] = "SafePropertyRead";
|
|
8808
|
+
/**
|
|
8809
|
+
* A safe keyed read requiring expansion into a null check.
|
|
8810
|
+
*/
|
|
8811
|
+
ExpressionKind[ExpressionKind["SafeKeyedRead"] = 13] = "SafeKeyedRead";
|
|
8812
|
+
/**
|
|
8813
|
+
* A safe function call requiring expansion into a null check.
|
|
8814
|
+
*/
|
|
8815
|
+
ExpressionKind[ExpressionKind["SafeInvokeFunction"] = 14] = "SafeInvokeFunction";
|
|
8816
|
+
/**
|
|
8817
|
+
* An intermediate expression that will be expanded from a safe read into an explicit ternary.
|
|
8818
|
+
*/
|
|
8819
|
+
ExpressionKind[ExpressionKind["SafeTernaryExpr"] = 15] = "SafeTernaryExpr";
|
|
8820
|
+
/**
|
|
8821
|
+
* An empty expression that will be stipped before generating the final output.
|
|
8822
|
+
*/
|
|
8823
|
+
ExpressionKind[ExpressionKind["EmptyExpr"] = 16] = "EmptyExpr";
|
|
8824
|
+
/*
|
|
8825
|
+
* An assignment to a temporary variable.
|
|
8826
|
+
*/
|
|
8827
|
+
ExpressionKind[ExpressionKind["AssignTemporaryExpr"] = 17] = "AssignTemporaryExpr";
|
|
8828
|
+
/**
|
|
8829
|
+
* A reference to a temporary variable.
|
|
8830
|
+
*/
|
|
8831
|
+
ExpressionKind[ExpressionKind["ReadTemporaryExpr"] = 18] = "ReadTemporaryExpr";
|
|
8832
|
+
/**
|
|
8833
|
+
* An expression representing a sanitizer function.
|
|
8834
|
+
*/
|
|
8835
|
+
ExpressionKind[ExpressionKind["SanitizerExpr"] = 19] = "SanitizerExpr";
|
|
8541
8836
|
})(ExpressionKind || (ExpressionKind = {}));
|
|
8542
8837
|
/**
|
|
8543
8838
|
* Distinguishes between different kinds of `SemanticVariable`s.
|
|
@@ -8557,11 +8852,188 @@ var SemanticVariableKind;
|
|
|
8557
8852
|
*/
|
|
8558
8853
|
SemanticVariableKind[SemanticVariableKind["SavedView"] = 2] = "SavedView";
|
|
8559
8854
|
})(SemanticVariableKind || (SemanticVariableKind = {}));
|
|
8855
|
+
/**
|
|
8856
|
+
* Whether to compile in compatibilty mode. In compatibility mode, the template pipeline will
|
|
8857
|
+
* attempt to match the output of `TemplateDefinitionBuilder` as exactly as possible, at the cost of
|
|
8858
|
+
* producing quirky or larger code in some cases.
|
|
8859
|
+
*/
|
|
8860
|
+
var CompatibilityMode;
|
|
8861
|
+
(function (CompatibilityMode) {
|
|
8862
|
+
CompatibilityMode[CompatibilityMode["Normal"] = 0] = "Normal";
|
|
8863
|
+
CompatibilityMode[CompatibilityMode["TemplateDefinitionBuilder"] = 1] = "TemplateDefinitionBuilder";
|
|
8864
|
+
})(CompatibilityMode || (CompatibilityMode = {}));
|
|
8865
|
+
/**
|
|
8866
|
+
* Represents functions used to sanitize different pieces of a template.
|
|
8867
|
+
*/
|
|
8868
|
+
var SanitizerFn;
|
|
8869
|
+
(function (SanitizerFn) {
|
|
8870
|
+
SanitizerFn[SanitizerFn["Html"] = 0] = "Html";
|
|
8871
|
+
SanitizerFn[SanitizerFn["Script"] = 1] = "Script";
|
|
8872
|
+
SanitizerFn[SanitizerFn["Style"] = 2] = "Style";
|
|
8873
|
+
SanitizerFn[SanitizerFn["Url"] = 3] = "Url";
|
|
8874
|
+
SanitizerFn[SanitizerFn["ResourceUrl"] = 4] = "ResourceUrl";
|
|
8875
|
+
SanitizerFn[SanitizerFn["IframeAttribute"] = 5] = "IframeAttribute";
|
|
8876
|
+
})(SanitizerFn || (SanitizerFn = {}));
|
|
8877
|
+
/**
|
|
8878
|
+
* Marker symbol for `UsesSlotIndex` trait.
|
|
8879
|
+
*/
|
|
8880
|
+
const UsesSlotIndex = Symbol('UsesSlotIndex');
|
|
8881
|
+
/**
|
|
8882
|
+
* Marker symbol for `ConsumesVars` trait.
|
|
8883
|
+
*/
|
|
8884
|
+
const ConsumesVarsTrait = Symbol('ConsumesVars');
|
|
8885
|
+
/**
|
|
8886
|
+
* Marker symbol for `UsesVarOffset` trait.
|
|
8887
|
+
*/
|
|
8888
|
+
const UsesVarOffset = Symbol('UsesVarOffset');
|
|
8889
|
+
class Interpolation {
|
|
8890
|
+
constructor(strings, expressions) {
|
|
8891
|
+
this.strings = strings;
|
|
8892
|
+
this.expressions = expressions;
|
|
8893
|
+
}
|
|
8894
|
+
}
|
|
8895
|
+
|
|
8896
|
+
var _d, _e, _f;
|
|
8897
|
+
/**
|
|
8898
|
+
* Base type used for all logical IR expressions.
|
|
8899
|
+
*/
|
|
8900
|
+
class ExpressionBase extends Expression {
|
|
8901
|
+
constructor(sourceSpan = null) {
|
|
8902
|
+
super(null, sourceSpan);
|
|
8903
|
+
}
|
|
8904
|
+
}
|
|
8905
|
+
class PipeBindingExpr extends ExpressionBase {
|
|
8906
|
+
static { _d = UsesSlotIndex, _e = ConsumesVarsTrait, _f = UsesVarOffset; }
|
|
8907
|
+
constructor(target, name, args) {
|
|
8908
|
+
super();
|
|
8909
|
+
this.target = target;
|
|
8910
|
+
this.name = name;
|
|
8911
|
+
this.args = args;
|
|
8912
|
+
this.kind = ExpressionKind.PipeBinding;
|
|
8913
|
+
this[_d] = true;
|
|
8914
|
+
this[_e] = true;
|
|
8915
|
+
this[_f] = true;
|
|
8916
|
+
this.slot = null;
|
|
8917
|
+
this.varOffset = null;
|
|
8918
|
+
}
|
|
8919
|
+
visitExpression(visitor, context) {
|
|
8920
|
+
for (const arg of this.args) {
|
|
8921
|
+
arg.visitExpression(visitor, context);
|
|
8922
|
+
}
|
|
8923
|
+
}
|
|
8924
|
+
isEquivalent() {
|
|
8925
|
+
return false;
|
|
8926
|
+
}
|
|
8927
|
+
isConstant() {
|
|
8928
|
+
return false;
|
|
8929
|
+
}
|
|
8930
|
+
transformInternalExpressions(transform, flags) {
|
|
8931
|
+
for (let idx = 0; idx < this.args.length; idx++) {
|
|
8932
|
+
this.args[idx] = transformExpressionsInExpression(this.args[idx], transform, flags);
|
|
8933
|
+
}
|
|
8934
|
+
}
|
|
8935
|
+
clone() {
|
|
8936
|
+
const r = new PipeBindingExpr(this.target, this.name, this.args.map(a => a.clone()));
|
|
8937
|
+
r.slot = this.slot;
|
|
8938
|
+
r.varOffset = this.varOffset;
|
|
8939
|
+
return r;
|
|
8940
|
+
}
|
|
8941
|
+
}
|
|
8942
|
+
class SafeInvokeFunctionExpr extends ExpressionBase {
|
|
8943
|
+
constructor(receiver, args) {
|
|
8944
|
+
super();
|
|
8945
|
+
this.receiver = receiver;
|
|
8946
|
+
this.args = args;
|
|
8947
|
+
this.kind = ExpressionKind.SafeInvokeFunction;
|
|
8948
|
+
}
|
|
8949
|
+
visitExpression(visitor, context) {
|
|
8950
|
+
this.receiver.visitExpression(visitor, context);
|
|
8951
|
+
for (const a of this.args) {
|
|
8952
|
+
a.visitExpression(visitor, context);
|
|
8953
|
+
}
|
|
8954
|
+
}
|
|
8955
|
+
isEquivalent() {
|
|
8956
|
+
return false;
|
|
8957
|
+
}
|
|
8958
|
+
isConstant() {
|
|
8959
|
+
return false;
|
|
8960
|
+
}
|
|
8961
|
+
transformInternalExpressions(transform, flags) {
|
|
8962
|
+
this.receiver = transformExpressionsInExpression(this.receiver, transform, flags);
|
|
8963
|
+
for (let i = 0; i < this.args.length; i++) {
|
|
8964
|
+
this.args[i] = transformExpressionsInExpression(this.args[i], transform, flags);
|
|
8965
|
+
}
|
|
8966
|
+
}
|
|
8967
|
+
clone() {
|
|
8968
|
+
return new SafeInvokeFunctionExpr(this.receiver.clone(), this.args.map(a => a.clone()));
|
|
8969
|
+
}
|
|
8970
|
+
}
|
|
8560
8971
|
var VisitorContextFlag;
|
|
8561
8972
|
(function (VisitorContextFlag) {
|
|
8562
8973
|
VisitorContextFlag[VisitorContextFlag["None"] = 0] = "None";
|
|
8563
8974
|
VisitorContextFlag[VisitorContextFlag["InChildOperation"] = 1] = "InChildOperation";
|
|
8564
8975
|
})(VisitorContextFlag || (VisitorContextFlag = {}));
|
|
8976
|
+
/**
|
|
8977
|
+
* Transform all `Expression`s in the AST of `expr` with the `transform` function.
|
|
8978
|
+
*
|
|
8979
|
+
* All such operations will be replaced with the result of applying `transform`, which may be an
|
|
8980
|
+
* identity transformation.
|
|
8981
|
+
*/
|
|
8982
|
+
function transformExpressionsInExpression(expr, transform, flags) {
|
|
8983
|
+
if (expr instanceof ExpressionBase) {
|
|
8984
|
+
expr.transformInternalExpressions(transform, flags);
|
|
8985
|
+
}
|
|
8986
|
+
else if (expr instanceof BinaryOperatorExpr) {
|
|
8987
|
+
expr.lhs = transformExpressionsInExpression(expr.lhs, transform, flags);
|
|
8988
|
+
expr.rhs = transformExpressionsInExpression(expr.rhs, transform, flags);
|
|
8989
|
+
}
|
|
8990
|
+
else if (expr instanceof ReadPropExpr) {
|
|
8991
|
+
expr.receiver = transformExpressionsInExpression(expr.receiver, transform, flags);
|
|
8992
|
+
}
|
|
8993
|
+
else if (expr instanceof ReadKeyExpr) {
|
|
8994
|
+
expr.receiver = transformExpressionsInExpression(expr.receiver, transform, flags);
|
|
8995
|
+
expr.index = transformExpressionsInExpression(expr.index, transform, flags);
|
|
8996
|
+
}
|
|
8997
|
+
else if (expr instanceof WritePropExpr) {
|
|
8998
|
+
expr.receiver = transformExpressionsInExpression(expr.receiver, transform, flags);
|
|
8999
|
+
expr.value = transformExpressionsInExpression(expr.value, transform, flags);
|
|
9000
|
+
}
|
|
9001
|
+
else if (expr instanceof WriteKeyExpr) {
|
|
9002
|
+
expr.receiver = transformExpressionsInExpression(expr.receiver, transform, flags);
|
|
9003
|
+
expr.index = transformExpressionsInExpression(expr.index, transform, flags);
|
|
9004
|
+
expr.value = transformExpressionsInExpression(expr.value, transform, flags);
|
|
9005
|
+
}
|
|
9006
|
+
else if (expr instanceof InvokeFunctionExpr) {
|
|
9007
|
+
expr.fn = transformExpressionsInExpression(expr.fn, transform, flags);
|
|
9008
|
+
for (let i = 0; i < expr.args.length; i++) {
|
|
9009
|
+
expr.args[i] = transformExpressionsInExpression(expr.args[i], transform, flags);
|
|
9010
|
+
}
|
|
9011
|
+
}
|
|
9012
|
+
else if (expr instanceof LiteralArrayExpr) {
|
|
9013
|
+
for (let i = 0; i < expr.entries.length; i++) {
|
|
9014
|
+
expr.entries[i] = transformExpressionsInExpression(expr.entries[i], transform, flags);
|
|
9015
|
+
}
|
|
9016
|
+
}
|
|
9017
|
+
else if (expr instanceof LiteralMapExpr) {
|
|
9018
|
+
for (let i = 0; i < expr.entries.length; i++) {
|
|
9019
|
+
expr.entries[i].value =
|
|
9020
|
+
transformExpressionsInExpression(expr.entries[i].value, transform, flags);
|
|
9021
|
+
}
|
|
9022
|
+
}
|
|
9023
|
+
else if (expr instanceof ConditionalExpr) {
|
|
9024
|
+
expr.condition = transformExpressionsInExpression(expr.condition, transform, flags);
|
|
9025
|
+
expr.trueCase = transformExpressionsInExpression(expr.trueCase, transform, flags);
|
|
9026
|
+
if (expr.falseCase !== null) {
|
|
9027
|
+
expr.falseCase = transformExpressionsInExpression(expr.falseCase, transform, flags);
|
|
9028
|
+
}
|
|
9029
|
+
}
|
|
9030
|
+
else if (expr instanceof ReadVarExpr || expr instanceof ExternalExpr ||
|
|
9031
|
+
expr instanceof LiteralExpr) ;
|
|
9032
|
+
else {
|
|
9033
|
+
throw new Error(`Unhandled expression kind: ${expr.constructor.name}`);
|
|
9034
|
+
}
|
|
9035
|
+
return transform(expr, flags);
|
|
9036
|
+
}
|
|
8565
9037
|
|
|
8566
9038
|
/**
|
|
8567
9039
|
* A linked list of `Op` nodes of a given subtype.
|
|
@@ -8741,22 +9213,38 @@ class OpList {
|
|
|
8741
9213
|
op.next = null;
|
|
8742
9214
|
}
|
|
8743
9215
|
/**
|
|
8744
|
-
* Insert `op` before `
|
|
9216
|
+
* Insert `op` before `target`.
|
|
8745
9217
|
*/
|
|
8746
|
-
static insertBefore(op,
|
|
8747
|
-
OpList.assertIsOwned(
|
|
8748
|
-
if (
|
|
9218
|
+
static insertBefore(op, target) {
|
|
9219
|
+
OpList.assertIsOwned(target);
|
|
9220
|
+
if (target.prev === null) {
|
|
8749
9221
|
throw new Error(`AssertionError: illegal operation on list start`);
|
|
8750
9222
|
}
|
|
8751
9223
|
OpList.assertIsNotEnd(op);
|
|
8752
9224
|
OpList.assertIsUnowned(op);
|
|
8753
|
-
op.debugListId =
|
|
9225
|
+
op.debugListId = target.debugListId;
|
|
8754
9226
|
// Just in case.
|
|
8755
9227
|
op.prev = null;
|
|
8756
|
-
|
|
8757
|
-
op.prev =
|
|
8758
|
-
op.next =
|
|
8759
|
-
|
|
9228
|
+
target.prev.next = op;
|
|
9229
|
+
op.prev = target.prev;
|
|
9230
|
+
op.next = target;
|
|
9231
|
+
target.prev = op;
|
|
9232
|
+
}
|
|
9233
|
+
/**
|
|
9234
|
+
* Insert `op` after `target`.
|
|
9235
|
+
*/
|
|
9236
|
+
static insertAfter(op, target) {
|
|
9237
|
+
OpList.assertIsOwned(target);
|
|
9238
|
+
if (target.next === null) {
|
|
9239
|
+
throw new Error(`AssertionError: illegal operation on list end`);
|
|
9240
|
+
}
|
|
9241
|
+
OpList.assertIsNotEnd(op);
|
|
9242
|
+
OpList.assertIsUnowned(op);
|
|
9243
|
+
op.debugListId = target.debugListId;
|
|
9244
|
+
target.next.prev = op;
|
|
9245
|
+
op.next = target.next;
|
|
9246
|
+
op.prev = target;
|
|
9247
|
+
target.next = op;
|
|
8760
9248
|
}
|
|
8761
9249
|
/**
|
|
8762
9250
|
* Asserts that `op` does not currently belong to a list.
|
|
@@ -8788,18 +9276,205 @@ class OpList {
|
|
|
8788
9276
|
}
|
|
8789
9277
|
}
|
|
8790
9278
|
|
|
8791
|
-
|
|
8792
|
-
|
|
8793
|
-
|
|
9279
|
+
/**
|
|
9280
|
+
* The set of OpKinds that represent the creation of an element or container
|
|
9281
|
+
*/
|
|
9282
|
+
new Set([
|
|
9283
|
+
OpKind.Element, OpKind.ElementStart, OpKind.Container, OpKind.ContainerStart, OpKind.Template
|
|
8794
9284
|
]);
|
|
8795
|
-
[
|
|
8796
|
-
Identifiers.pipeBind1,
|
|
8797
|
-
Identifiers.pipeBind2,
|
|
8798
|
-
Identifiers.pipeBind3,
|
|
8799
|
-
Identifiers.pipeBind4,
|
|
8800
|
-
];
|
|
8801
9285
|
/**
|
|
8802
|
-
*
|
|
9286
|
+
* Whether the active namespace is HTML, MathML, or SVG mode.
|
|
9287
|
+
*/
|
|
9288
|
+
var Namespace;
|
|
9289
|
+
(function (Namespace) {
|
|
9290
|
+
Namespace[Namespace["HTML"] = 0] = "HTML";
|
|
9291
|
+
Namespace[Namespace["SVG"] = 1] = "SVG";
|
|
9292
|
+
Namespace[Namespace["Math"] = 2] = "Math";
|
|
9293
|
+
})(Namespace || (Namespace = {}));
|
|
9294
|
+
|
|
9295
|
+
/**
|
|
9296
|
+
* Parses string representation of a style and converts it into object literal.
|
|
9297
|
+
*
|
|
9298
|
+
* @param value string representation of style as used in the `style` attribute in HTML.
|
|
9299
|
+
* Example: `color: red; height: auto`.
|
|
9300
|
+
* @returns An array of style property name and value pairs, e.g. `['color', 'red', 'height',
|
|
9301
|
+
* 'auto']`
|
|
9302
|
+
*/
|
|
9303
|
+
function parse(value) {
|
|
9304
|
+
// we use a string array here instead of a string map
|
|
9305
|
+
// because a string-map is not guaranteed to retain the
|
|
9306
|
+
// order of the entries whereas a string array can be
|
|
9307
|
+
// constructed in a [key, value, key, value] format.
|
|
9308
|
+
const styles = [];
|
|
9309
|
+
let i = 0;
|
|
9310
|
+
let parenDepth = 0;
|
|
9311
|
+
let quote = 0 /* Char.QuoteNone */;
|
|
9312
|
+
let valueStart = 0;
|
|
9313
|
+
let propStart = 0;
|
|
9314
|
+
let currentProp = null;
|
|
9315
|
+
while (i < value.length) {
|
|
9316
|
+
const token = value.charCodeAt(i++);
|
|
9317
|
+
switch (token) {
|
|
9318
|
+
case 40 /* Char.OpenParen */:
|
|
9319
|
+
parenDepth++;
|
|
9320
|
+
break;
|
|
9321
|
+
case 41 /* Char.CloseParen */:
|
|
9322
|
+
parenDepth--;
|
|
9323
|
+
break;
|
|
9324
|
+
case 39 /* Char.QuoteSingle */:
|
|
9325
|
+
// valueStart needs to be there since prop values don't
|
|
9326
|
+
// have quotes in CSS
|
|
9327
|
+
if (quote === 0 /* Char.QuoteNone */) {
|
|
9328
|
+
quote = 39 /* Char.QuoteSingle */;
|
|
9329
|
+
}
|
|
9330
|
+
else if (quote === 39 /* Char.QuoteSingle */ && value.charCodeAt(i - 1) !== 92 /* Char.BackSlash */) {
|
|
9331
|
+
quote = 0 /* Char.QuoteNone */;
|
|
9332
|
+
}
|
|
9333
|
+
break;
|
|
9334
|
+
case 34 /* Char.QuoteDouble */:
|
|
9335
|
+
// same logic as above
|
|
9336
|
+
if (quote === 0 /* Char.QuoteNone */) {
|
|
9337
|
+
quote = 34 /* Char.QuoteDouble */;
|
|
9338
|
+
}
|
|
9339
|
+
else if (quote === 34 /* Char.QuoteDouble */ && value.charCodeAt(i - 1) !== 92 /* Char.BackSlash */) {
|
|
9340
|
+
quote = 0 /* Char.QuoteNone */;
|
|
9341
|
+
}
|
|
9342
|
+
break;
|
|
9343
|
+
case 58 /* Char.Colon */:
|
|
9344
|
+
if (!currentProp && parenDepth === 0 && quote === 0 /* Char.QuoteNone */) {
|
|
9345
|
+
currentProp = hyphenate$1(value.substring(propStart, i - 1).trim());
|
|
9346
|
+
valueStart = i;
|
|
9347
|
+
}
|
|
9348
|
+
break;
|
|
9349
|
+
case 59 /* Char.Semicolon */:
|
|
9350
|
+
if (currentProp && valueStart > 0 && parenDepth === 0 && quote === 0 /* Char.QuoteNone */) {
|
|
9351
|
+
const styleVal = value.substring(valueStart, i - 1).trim();
|
|
9352
|
+
styles.push(currentProp, styleVal);
|
|
9353
|
+
propStart = i;
|
|
9354
|
+
valueStart = 0;
|
|
9355
|
+
currentProp = null;
|
|
9356
|
+
}
|
|
9357
|
+
break;
|
|
9358
|
+
}
|
|
9359
|
+
}
|
|
9360
|
+
if (currentProp && valueStart) {
|
|
9361
|
+
const styleVal = value.slice(valueStart).trim();
|
|
9362
|
+
styles.push(currentProp, styleVal);
|
|
9363
|
+
}
|
|
9364
|
+
return styles;
|
|
9365
|
+
}
|
|
9366
|
+
function hyphenate$1(value) {
|
|
9367
|
+
return value
|
|
9368
|
+
.replace(/[a-z][A-Z]/g, v => {
|
|
9369
|
+
return v.charAt(0) + '-' + v.charAt(1);
|
|
9370
|
+
})
|
|
9371
|
+
.toLowerCase();
|
|
9372
|
+
}
|
|
9373
|
+
|
|
9374
|
+
new Set([
|
|
9375
|
+
Identifiers.elementStart,
|
|
9376
|
+
Identifiers.elementEnd,
|
|
9377
|
+
Identifiers.element,
|
|
9378
|
+
Identifiers.property,
|
|
9379
|
+
Identifiers.hostProperty,
|
|
9380
|
+
Identifiers.styleProp,
|
|
9381
|
+
Identifiers.attribute,
|
|
9382
|
+
Identifiers.stylePropInterpolate1,
|
|
9383
|
+
Identifiers.stylePropInterpolate2,
|
|
9384
|
+
Identifiers.stylePropInterpolate3,
|
|
9385
|
+
Identifiers.stylePropInterpolate4,
|
|
9386
|
+
Identifiers.stylePropInterpolate5,
|
|
9387
|
+
Identifiers.stylePropInterpolate6,
|
|
9388
|
+
Identifiers.stylePropInterpolate7,
|
|
9389
|
+
Identifiers.stylePropInterpolate8,
|
|
9390
|
+
Identifiers.stylePropInterpolateV,
|
|
9391
|
+
Identifiers.classProp,
|
|
9392
|
+
Identifiers.listener,
|
|
9393
|
+
Identifiers.elementContainerStart,
|
|
9394
|
+
Identifiers.elementContainerEnd,
|
|
9395
|
+
Identifiers.elementContainer,
|
|
9396
|
+
Identifiers.listener,
|
|
9397
|
+
]);
|
|
9398
|
+
|
|
9399
|
+
new Map([
|
|
9400
|
+
[OpKind.ElementEnd, [OpKind.ElementStart, OpKind.Element]],
|
|
9401
|
+
[OpKind.ContainerEnd, [OpKind.ContainerStart, OpKind.Container]],
|
|
9402
|
+
]);
|
|
9403
|
+
// A lookup set of all the expression kinds that require a temporary variable to be generated.
|
|
9404
|
+
[
|
|
9405
|
+
InvokeFunctionExpr, LiteralArrayExpr, LiteralMapExpr, SafeInvokeFunctionExpr,
|
|
9406
|
+
PipeBindingExpr
|
|
9407
|
+
].map(e => e.constructor.name);
|
|
9408
|
+
|
|
9409
|
+
new Map([
|
|
9410
|
+
['&&', exports.BinaryOperator.And],
|
|
9411
|
+
['>', exports.BinaryOperator.Bigger],
|
|
9412
|
+
['>=', exports.BinaryOperator.BiggerEquals],
|
|
9413
|
+
['&', exports.BinaryOperator.BitwiseAnd],
|
|
9414
|
+
['/', exports.BinaryOperator.Divide],
|
|
9415
|
+
['==', exports.BinaryOperator.Equals],
|
|
9416
|
+
['===', exports.BinaryOperator.Identical],
|
|
9417
|
+
['<', exports.BinaryOperator.Lower],
|
|
9418
|
+
['<=', exports.BinaryOperator.LowerEquals],
|
|
9419
|
+
['-', exports.BinaryOperator.Minus],
|
|
9420
|
+
['%', exports.BinaryOperator.Modulo],
|
|
9421
|
+
['*', exports.BinaryOperator.Multiply],
|
|
9422
|
+
['!=', exports.BinaryOperator.NotEquals],
|
|
9423
|
+
['!==', exports.BinaryOperator.NotIdentical],
|
|
9424
|
+
['??', exports.BinaryOperator.NullishCoalesce],
|
|
9425
|
+
['||', exports.BinaryOperator.Or],
|
|
9426
|
+
['+', exports.BinaryOperator.Plus],
|
|
9427
|
+
]);
|
|
9428
|
+
new Map([['svg', Namespace.SVG], ['math', Namespace.Math]]);
|
|
9429
|
+
|
|
9430
|
+
function kindTest(kind) {
|
|
9431
|
+
return (op) => op.kind === kind;
|
|
9432
|
+
}
|
|
9433
|
+
/**
|
|
9434
|
+
* Defines the groups based on `OpKind` that ops will be divided into. Ops will be collected into
|
|
9435
|
+
* groups, then optionally transformed, before recombining the groups in the order defined here.
|
|
9436
|
+
*/
|
|
9437
|
+
[
|
|
9438
|
+
{ test: kindTest(OpKind.StyleMap), transform: keepLast },
|
|
9439
|
+
{ test: kindTest(OpKind.ClassMap), transform: keepLast },
|
|
9440
|
+
{ test: kindTest(OpKind.StyleProp) },
|
|
9441
|
+
{ test: kindTest(OpKind.ClassProp) },
|
|
9442
|
+
{
|
|
9443
|
+
test: (op) => (op.kind === OpKind.Property || op.kind === OpKind.HostProperty) &&
|
|
9444
|
+
op.expression instanceof Interpolation
|
|
9445
|
+
},
|
|
9446
|
+
{
|
|
9447
|
+
test: (op) => (op.kind === OpKind.Property || op.kind === OpKind.HostProperty) &&
|
|
9448
|
+
!(op.expression instanceof Interpolation)
|
|
9449
|
+
},
|
|
9450
|
+
{ test: kindTest(OpKind.Attribute) },
|
|
9451
|
+
];
|
|
9452
|
+
/**
|
|
9453
|
+
* The set of all op kinds we handle in the reordering phase.
|
|
9454
|
+
*/
|
|
9455
|
+
new Set([
|
|
9456
|
+
OpKind.StyleMap,
|
|
9457
|
+
OpKind.ClassMap,
|
|
9458
|
+
OpKind.StyleProp,
|
|
9459
|
+
OpKind.ClassProp,
|
|
9460
|
+
OpKind.Property,
|
|
9461
|
+
OpKind.HostProperty,
|
|
9462
|
+
OpKind.Attribute,
|
|
9463
|
+
]);
|
|
9464
|
+
/**
|
|
9465
|
+
* Keeps only the last op in a list of ops.
|
|
9466
|
+
*/
|
|
9467
|
+
function keepLast(ops) {
|
|
9468
|
+
return ops.slice(ops.length - 1);
|
|
9469
|
+
}
|
|
9470
|
+
[
|
|
9471
|
+
Identifiers.pipeBind1,
|
|
9472
|
+
Identifiers.pipeBind2,
|
|
9473
|
+
Identifiers.pipeBind3,
|
|
9474
|
+
Identifiers.pipeBind4,
|
|
9475
|
+
];
|
|
9476
|
+
/**
|
|
9477
|
+
* `InterpolationConfig` for the `textInterpolate` instruction.
|
|
8803
9478
|
*/
|
|
8804
9479
|
({
|
|
8805
9480
|
constant: [
|
|
@@ -8844,6 +9519,98 @@ new Map([
|
|
|
8844
9519
|
return (n - 1) / 2;
|
|
8845
9520
|
},
|
|
8846
9521
|
});
|
|
9522
|
+
/**
|
|
9523
|
+
* `InterpolationConfig` for the `stylePropInterpolate` instruction.
|
|
9524
|
+
*/
|
|
9525
|
+
({
|
|
9526
|
+
constant: [
|
|
9527
|
+
Identifiers.styleProp,
|
|
9528
|
+
Identifiers.stylePropInterpolate1,
|
|
9529
|
+
Identifiers.stylePropInterpolate2,
|
|
9530
|
+
Identifiers.stylePropInterpolate3,
|
|
9531
|
+
Identifiers.stylePropInterpolate4,
|
|
9532
|
+
Identifiers.stylePropInterpolate5,
|
|
9533
|
+
Identifiers.stylePropInterpolate6,
|
|
9534
|
+
Identifiers.stylePropInterpolate7,
|
|
9535
|
+
Identifiers.stylePropInterpolate8,
|
|
9536
|
+
],
|
|
9537
|
+
variable: Identifiers.stylePropInterpolateV,
|
|
9538
|
+
mapping: n => {
|
|
9539
|
+
if (n % 2 === 0) {
|
|
9540
|
+
throw new Error(`Expected odd number of arguments`);
|
|
9541
|
+
}
|
|
9542
|
+
return (n - 1) / 2;
|
|
9543
|
+
},
|
|
9544
|
+
});
|
|
9545
|
+
/**
|
|
9546
|
+
* `InterpolationConfig` for the `attributeInterpolate` instruction.
|
|
9547
|
+
*/
|
|
9548
|
+
({
|
|
9549
|
+
constant: [
|
|
9550
|
+
Identifiers.attribute,
|
|
9551
|
+
Identifiers.attributeInterpolate1,
|
|
9552
|
+
Identifiers.attributeInterpolate2,
|
|
9553
|
+
Identifiers.attributeInterpolate3,
|
|
9554
|
+
Identifiers.attributeInterpolate4,
|
|
9555
|
+
Identifiers.attributeInterpolate5,
|
|
9556
|
+
Identifiers.attributeInterpolate6,
|
|
9557
|
+
Identifiers.attributeInterpolate7,
|
|
9558
|
+
Identifiers.attributeInterpolate8,
|
|
9559
|
+
],
|
|
9560
|
+
variable: Identifiers.attributeInterpolateV,
|
|
9561
|
+
mapping: n => {
|
|
9562
|
+
if (n % 2 === 0) {
|
|
9563
|
+
throw new Error(`Expected odd number of arguments`);
|
|
9564
|
+
}
|
|
9565
|
+
return (n - 1) / 2;
|
|
9566
|
+
},
|
|
9567
|
+
});
|
|
9568
|
+
/**
|
|
9569
|
+
* `InterpolationConfig` for the `styleMapInterpolate` instruction.
|
|
9570
|
+
*/
|
|
9571
|
+
({
|
|
9572
|
+
constant: [
|
|
9573
|
+
Identifiers.styleMap,
|
|
9574
|
+
Identifiers.styleMapInterpolate1,
|
|
9575
|
+
Identifiers.styleMapInterpolate2,
|
|
9576
|
+
Identifiers.styleMapInterpolate3,
|
|
9577
|
+
Identifiers.styleMapInterpolate4,
|
|
9578
|
+
Identifiers.styleMapInterpolate5,
|
|
9579
|
+
Identifiers.styleMapInterpolate6,
|
|
9580
|
+
Identifiers.styleMapInterpolate7,
|
|
9581
|
+
Identifiers.styleMapInterpolate8,
|
|
9582
|
+
],
|
|
9583
|
+
variable: Identifiers.styleMapInterpolateV,
|
|
9584
|
+
mapping: n => {
|
|
9585
|
+
if (n % 2 === 0) {
|
|
9586
|
+
throw new Error(`Expected odd number of arguments`);
|
|
9587
|
+
}
|
|
9588
|
+
return (n - 1) / 2;
|
|
9589
|
+
},
|
|
9590
|
+
});
|
|
9591
|
+
/**
|
|
9592
|
+
* `InterpolationConfig` for the `classMapInterpolate` instruction.
|
|
9593
|
+
*/
|
|
9594
|
+
({
|
|
9595
|
+
constant: [
|
|
9596
|
+
Identifiers.classMap,
|
|
9597
|
+
Identifiers.classMapInterpolate1,
|
|
9598
|
+
Identifiers.classMapInterpolate2,
|
|
9599
|
+
Identifiers.classMapInterpolate3,
|
|
9600
|
+
Identifiers.classMapInterpolate4,
|
|
9601
|
+
Identifiers.classMapInterpolate5,
|
|
9602
|
+
Identifiers.classMapInterpolate6,
|
|
9603
|
+
Identifiers.classMapInterpolate7,
|
|
9604
|
+
Identifiers.classMapInterpolate8,
|
|
9605
|
+
],
|
|
9606
|
+
variable: Identifiers.classMapInterpolateV,
|
|
9607
|
+
mapping: n => {
|
|
9608
|
+
if (n % 2 === 0) {
|
|
9609
|
+
throw new Error(`Expected odd number of arguments`);
|
|
9610
|
+
}
|
|
9611
|
+
return (n - 1) / 2;
|
|
9612
|
+
},
|
|
9613
|
+
});
|
|
8847
9614
|
({
|
|
8848
9615
|
constant: [
|
|
8849
9616
|
Identifiers.pureFunction0,
|
|
@@ -8859,6 +9626,26 @@ new Map([
|
|
|
8859
9626
|
variable: Identifiers.pureFunctionV,
|
|
8860
9627
|
mapping: n => n,
|
|
8861
9628
|
});
|
|
9629
|
+
|
|
9630
|
+
/**
|
|
9631
|
+
* Map of sanitizers to their identifier.
|
|
9632
|
+
*/
|
|
9633
|
+
new Map([
|
|
9634
|
+
[SanitizerFn.Html, Identifiers.sanitizeHtml],
|
|
9635
|
+
[SanitizerFn.IframeAttribute, Identifiers.validateIframeAttribute],
|
|
9636
|
+
[SanitizerFn.ResourceUrl, Identifiers.sanitizeResourceUrl],
|
|
9637
|
+
[SanitizerFn.Script, Identifiers.sanitizeScript],
|
|
9638
|
+
[SanitizerFn.Style, Identifiers.sanitizeStyle], [SanitizerFn.Url, Identifiers.sanitizeUrl]
|
|
9639
|
+
]);
|
|
9640
|
+
|
|
9641
|
+
/**
|
|
9642
|
+
* Mapping of security contexts to sanitizer function for that context.
|
|
9643
|
+
*/
|
|
9644
|
+
new Map([
|
|
9645
|
+
[SecurityContext.HTML, SanitizerFn.Html], [SecurityContext.SCRIPT, SanitizerFn.Script],
|
|
9646
|
+
[SecurityContext.STYLE, SanitizerFn.Style], [SecurityContext.URL, SanitizerFn.Url],
|
|
9647
|
+
[SecurityContext.RESOURCE_URL, SanitizerFn.ResourceUrl]
|
|
9648
|
+
]);
|
|
8862
9649
|
/**
|
|
8863
9650
|
* A [fence](https://en.wikipedia.org/wiki/Memory_barrier) flag for an expression which indicates
|
|
8864
9651
|
* how that expression can be optimized in relation to other expressions or instructions.
|
|
@@ -8893,114 +9680,15 @@ var Fence;
|
|
|
8893
9680
|
Fence[Fence["SideEffectful"] = 4] = "SideEffectful";
|
|
8894
9681
|
})(Fence || (Fence = {}));
|
|
8895
9682
|
|
|
8896
|
-
|
|
8897
|
-
Identifiers.elementStart,
|
|
8898
|
-
Identifiers.elementEnd,
|
|
8899
|
-
Identifiers.property,
|
|
8900
|
-
Identifiers.elementContainerStart,
|
|
8901
|
-
Identifiers.elementContainerEnd,
|
|
8902
|
-
Identifiers.elementContainer,
|
|
8903
|
-
]);
|
|
8904
|
-
|
|
9683
|
+
CompatibilityMode.TemplateDefinitionBuilder;
|
|
8905
9684
|
new Map([
|
|
8906
|
-
[
|
|
8907
|
-
[
|
|
8908
|
-
[
|
|
8909
|
-
[
|
|
8910
|
-
[
|
|
8911
|
-
['==', exports.BinaryOperator.Equals],
|
|
8912
|
-
['===', exports.BinaryOperator.Identical],
|
|
8913
|
-
['<', exports.BinaryOperator.Lower],
|
|
8914
|
-
['<=', exports.BinaryOperator.LowerEquals],
|
|
8915
|
-
['-', exports.BinaryOperator.Minus],
|
|
8916
|
-
['%', exports.BinaryOperator.Modulo],
|
|
8917
|
-
['*', exports.BinaryOperator.Multiply],
|
|
8918
|
-
['!=', exports.BinaryOperator.NotEquals],
|
|
8919
|
-
['!==', exports.BinaryOperator.NotIdentical],
|
|
8920
|
-
['??', exports.BinaryOperator.NullishCoalesce],
|
|
8921
|
-
['||', exports.BinaryOperator.Or],
|
|
8922
|
-
['+', exports.BinaryOperator.Plus],
|
|
9685
|
+
[0 /* e.BindingType.Property */, BindingKind.Property],
|
|
9686
|
+
[1 /* e.BindingType.Attribute */, BindingKind.Attribute],
|
|
9687
|
+
[2 /* e.BindingType.Class */, BindingKind.ClassName],
|
|
9688
|
+
[3 /* e.BindingType.Style */, BindingKind.StyleProperty],
|
|
9689
|
+
[4 /* e.BindingType.Animation */, BindingKind.Animation],
|
|
8923
9690
|
]);
|
|
8924
9691
|
|
|
8925
|
-
/**
|
|
8926
|
-
* Parses string representation of a style and converts it into object literal.
|
|
8927
|
-
*
|
|
8928
|
-
* @param value string representation of style as used in the `style` attribute in HTML.
|
|
8929
|
-
* Example: `color: red; height: auto`.
|
|
8930
|
-
* @returns An array of style property name and value pairs, e.g. `['color', 'red', 'height',
|
|
8931
|
-
* 'auto']`
|
|
8932
|
-
*/
|
|
8933
|
-
function parse(value) {
|
|
8934
|
-
// we use a string array here instead of a string map
|
|
8935
|
-
// because a string-map is not guaranteed to retain the
|
|
8936
|
-
// order of the entries whereas a string array can be
|
|
8937
|
-
// constructed in a [key, value, key, value] format.
|
|
8938
|
-
const styles = [];
|
|
8939
|
-
let i = 0;
|
|
8940
|
-
let parenDepth = 0;
|
|
8941
|
-
let quote = 0 /* Char.QuoteNone */;
|
|
8942
|
-
let valueStart = 0;
|
|
8943
|
-
let propStart = 0;
|
|
8944
|
-
let currentProp = null;
|
|
8945
|
-
while (i < value.length) {
|
|
8946
|
-
const token = value.charCodeAt(i++);
|
|
8947
|
-
switch (token) {
|
|
8948
|
-
case 40 /* Char.OpenParen */:
|
|
8949
|
-
parenDepth++;
|
|
8950
|
-
break;
|
|
8951
|
-
case 41 /* Char.CloseParen */:
|
|
8952
|
-
parenDepth--;
|
|
8953
|
-
break;
|
|
8954
|
-
case 39 /* Char.QuoteSingle */:
|
|
8955
|
-
// valueStart needs to be there since prop values don't
|
|
8956
|
-
// have quotes in CSS
|
|
8957
|
-
if (quote === 0 /* Char.QuoteNone */) {
|
|
8958
|
-
quote = 39 /* Char.QuoteSingle */;
|
|
8959
|
-
}
|
|
8960
|
-
else if (quote === 39 /* Char.QuoteSingle */ && value.charCodeAt(i - 1) !== 92 /* Char.BackSlash */) {
|
|
8961
|
-
quote = 0 /* Char.QuoteNone */;
|
|
8962
|
-
}
|
|
8963
|
-
break;
|
|
8964
|
-
case 34 /* Char.QuoteDouble */:
|
|
8965
|
-
// same logic as above
|
|
8966
|
-
if (quote === 0 /* Char.QuoteNone */) {
|
|
8967
|
-
quote = 34 /* Char.QuoteDouble */;
|
|
8968
|
-
}
|
|
8969
|
-
else if (quote === 34 /* Char.QuoteDouble */ && value.charCodeAt(i - 1) !== 92 /* Char.BackSlash */) {
|
|
8970
|
-
quote = 0 /* Char.QuoteNone */;
|
|
8971
|
-
}
|
|
8972
|
-
break;
|
|
8973
|
-
case 58 /* Char.Colon */:
|
|
8974
|
-
if (!currentProp && parenDepth === 0 && quote === 0 /* Char.QuoteNone */) {
|
|
8975
|
-
currentProp = hyphenate(value.substring(propStart, i - 1).trim());
|
|
8976
|
-
valueStart = i;
|
|
8977
|
-
}
|
|
8978
|
-
break;
|
|
8979
|
-
case 59 /* Char.Semicolon */:
|
|
8980
|
-
if (currentProp && valueStart > 0 && parenDepth === 0 && quote === 0 /* Char.QuoteNone */) {
|
|
8981
|
-
const styleVal = value.substring(valueStart, i - 1).trim();
|
|
8982
|
-
styles.push(currentProp, styleVal);
|
|
8983
|
-
propStart = i;
|
|
8984
|
-
valueStart = 0;
|
|
8985
|
-
currentProp = null;
|
|
8986
|
-
}
|
|
8987
|
-
break;
|
|
8988
|
-
}
|
|
8989
|
-
}
|
|
8990
|
-
if (currentProp && valueStart) {
|
|
8991
|
-
const styleVal = value.slice(valueStart).trim();
|
|
8992
|
-
styles.push(currentProp, styleVal);
|
|
8993
|
-
}
|
|
8994
|
-
return styles;
|
|
8995
|
-
}
|
|
8996
|
-
function hyphenate(value) {
|
|
8997
|
-
return value
|
|
8998
|
-
.replace(/[a-z][A-Z]/g, v => {
|
|
8999
|
-
return v.charAt(0) + '-' + v.charAt(1);
|
|
9000
|
-
})
|
|
9001
|
-
.toLowerCase();
|
|
9002
|
-
}
|
|
9003
|
-
|
|
9004
9692
|
const IMPORTANT_FLAG = '!important';
|
|
9005
9693
|
/**
|
|
9006
9694
|
* Minimum amount of binding slots required in the runtime for style/class bindings.
|
|
@@ -9170,7 +9858,7 @@ class StylingBuilder {
|
|
|
9170
9858
|
// CSS custom properties are case-sensitive so we shouldn't normalize them.
|
|
9171
9859
|
// See: https://www.w3.org/TR/css-variables-1/#defining-variables
|
|
9172
9860
|
if (!isCssCustomProperty(name)) {
|
|
9173
|
-
name = hyphenate(name);
|
|
9861
|
+
name = hyphenate$1(name);
|
|
9174
9862
|
}
|
|
9175
9863
|
const { property, hasOverrideFlag, suffix: bindingSuffix } = parseProperty(name);
|
|
9176
9864
|
suffix = typeof suffix === 'string' && suffix.length !== 0 ? suffix : bindingSuffix;
|
|
@@ -9300,7 +9988,7 @@ class StylingBuilder {
|
|
|
9300
9988
|
// pipes can be picked up in time before the template is built
|
|
9301
9989
|
const mapValue = stylingInput.value.visit(valueConverter);
|
|
9302
9990
|
let reference;
|
|
9303
|
-
if (mapValue instanceof Interpolation) {
|
|
9991
|
+
if (mapValue instanceof Interpolation$1) {
|
|
9304
9992
|
totalBindingSlotsRequired += mapValue.expressions.length;
|
|
9305
9993
|
reference = isClassBased ? getClassMapInterpolationExpression(mapValue) :
|
|
9306
9994
|
getStyleMapInterpolationExpression(mapValue);
|
|
@@ -9335,7 +10023,7 @@ class StylingBuilder {
|
|
|
9335
10023
|
// We need to store the intermediate value so that we don't allocate
|
|
9336
10024
|
// the strings on each CD.
|
|
9337
10025
|
let totalBindingSlotsRequired = MIN_STYLING_BINDING_SLOTS_REQUIRED;
|
|
9338
|
-
if (value instanceof Interpolation) {
|
|
10026
|
+
if (value instanceof Interpolation$1) {
|
|
9339
10027
|
totalBindingSlotsRequired += value.expressions.length;
|
|
9340
10028
|
if (getInterpolationExpressionFn) {
|
|
9341
10029
|
referenceForCall = getInterpolationExpressionFn(value);
|
|
@@ -9527,7 +10215,7 @@ function isEmptyExpression(ast) {
|
|
|
9527
10215
|
if (ast instanceof ASTWithSource) {
|
|
9528
10216
|
ast = ast.ast;
|
|
9529
10217
|
}
|
|
9530
|
-
return ast instanceof EmptyExpr;
|
|
10218
|
+
return ast instanceof EmptyExpr$1;
|
|
9531
10219
|
}
|
|
9532
10220
|
|
|
9533
10221
|
exports.TokenType = void 0;
|
|
@@ -9977,6 +10665,7 @@ class Parser$1 {
|
|
|
9977
10665
|
ast.visit(checker);
|
|
9978
10666
|
return checker.errors;
|
|
9979
10667
|
}
|
|
10668
|
+
// Host bindings parsed here
|
|
9980
10669
|
parseSimpleBinding(input, location, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
|
|
9981
10670
|
const ast = this._parseBindingAst(input, location, absoluteOffset, interpolationConfig);
|
|
9982
10671
|
const errors = this.checkSimpleExpression(ast);
|
|
@@ -10059,7 +10748,7 @@ class Parser$1 {
|
|
|
10059
10748
|
}
|
|
10060
10749
|
createInterpolationAst(strings, expressions, input, location, absoluteOffset) {
|
|
10061
10750
|
const span = new ParseSpan(0, input.length);
|
|
10062
|
-
const interpolation = new Interpolation(span, span.toAbsolute(absoluteOffset), strings, expressions);
|
|
10751
|
+
const interpolation = new Interpolation$1(span, span.toAbsolute(absoluteOffset), strings, expressions);
|
|
10063
10752
|
return new ASTWithSource(interpolation, input, location, absoluteOffset, this.errors);
|
|
10064
10753
|
}
|
|
10065
10754
|
/**
|
|
@@ -10430,7 +11119,7 @@ class _ParseAST {
|
|
|
10430
11119
|
// We have no expressions so create an empty expression that spans the entire input length
|
|
10431
11120
|
const artificialStart = this.offset;
|
|
10432
11121
|
const artificialEnd = this.offset + this.input.length;
|
|
10433
|
-
return new EmptyExpr(this.span(artificialStart, artificialEnd), this.sourceSpan(artificialStart, artificialEnd));
|
|
11122
|
+
return new EmptyExpr$1(this.span(artificialStart, artificialEnd), this.sourceSpan(artificialStart, artificialEnd));
|
|
10434
11123
|
}
|
|
10435
11124
|
if (exprs.length == 1)
|
|
10436
11125
|
return exprs[0];
|
|
@@ -10491,7 +11180,7 @@ class _ParseAST {
|
|
|
10491
11180
|
const end = this.inputIndex;
|
|
10492
11181
|
const expression = this.input.substring(start, end);
|
|
10493
11182
|
this.error(`Conditional expression ${expression} requires all 3 expressions`);
|
|
10494
|
-
no = new EmptyExpr(this.span(start), this.sourceSpan(start));
|
|
11183
|
+
no = new EmptyExpr$1(this.span(start), this.sourceSpan(start));
|
|
10495
11184
|
}
|
|
10496
11185
|
else {
|
|
10497
11186
|
no = this.parsePipe();
|
|
@@ -10716,15 +11405,15 @@ class _ParseAST {
|
|
|
10716
11405
|
}
|
|
10717
11406
|
else if (this.next.isPrivateIdentifier()) {
|
|
10718
11407
|
this._reportErrorForPrivateIdentifier(this.next, null);
|
|
10719
|
-
return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
|
11408
|
+
return new EmptyExpr$1(this.span(start), this.sourceSpan(start));
|
|
10720
11409
|
}
|
|
10721
11410
|
else if (this.index >= this.tokens.length) {
|
|
10722
11411
|
this.error(`Unexpected end of expression: ${this.input}`);
|
|
10723
|
-
return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
|
11412
|
+
return new EmptyExpr$1(this.span(start), this.sourceSpan(start));
|
|
10724
11413
|
}
|
|
10725
11414
|
else {
|
|
10726
11415
|
this.error(`Unexpected token ${this.next}`);
|
|
10727
|
-
return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
|
11416
|
+
return new EmptyExpr$1(this.span(start), this.sourceSpan(start));
|
|
10728
11417
|
}
|
|
10729
11418
|
}
|
|
10730
11419
|
parseExpressionList(terminator) {
|
|
@@ -10785,7 +11474,7 @@ class _ParseAST {
|
|
|
10785
11474
|
if (isSafe) {
|
|
10786
11475
|
if (this.consumeOptionalAssignment()) {
|
|
10787
11476
|
this.error('The \'?.\' operator cannot be used in the assignment');
|
|
10788
|
-
receiver = new EmptyExpr(this.span(start), this.sourceSpan(start));
|
|
11477
|
+
receiver = new EmptyExpr$1(this.span(start), this.sourceSpan(start));
|
|
10789
11478
|
}
|
|
10790
11479
|
else {
|
|
10791
11480
|
receiver = new SafePropertyRead(this.span(start), this.sourceSpan(start), nameSpan, readReceiver, id);
|
|
@@ -10795,7 +11484,7 @@ class _ParseAST {
|
|
|
10795
11484
|
if (this.consumeOptionalAssignment()) {
|
|
10796
11485
|
if (!(this.parseFlags & 1 /* ParseFlags.Action */)) {
|
|
10797
11486
|
this.error('Bindings cannot contain assignments');
|
|
10798
|
-
return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
|
11487
|
+
return new EmptyExpr$1(this.span(start), this.sourceSpan(start));
|
|
10799
11488
|
}
|
|
10800
11489
|
const value = this.parseConditional();
|
|
10801
11490
|
receiver = new PropertyWrite(this.span(start), this.sourceSpan(start), nameSpan, readReceiver, id, value);
|
|
@@ -10925,7 +11614,7 @@ class _ParseAST {
|
|
|
10925
11614
|
return this.withContext(ParseContextFlags.Writable, () => {
|
|
10926
11615
|
this.rbracketsExpected++;
|
|
10927
11616
|
const key = this.parsePipe();
|
|
10928
|
-
if (key instanceof EmptyExpr) {
|
|
11617
|
+
if (key instanceof EmptyExpr$1) {
|
|
10929
11618
|
this.error(`Key access cannot be empty`);
|
|
10930
11619
|
}
|
|
10931
11620
|
this.rbracketsExpected--;
|
|
@@ -10943,7 +11632,7 @@ class _ParseAST {
|
|
|
10943
11632
|
return isSafe ? new SafeKeyedRead(this.span(start), this.sourceSpan(start), receiver, key) :
|
|
10944
11633
|
new KeyedRead(this.span(start), this.sourceSpan(start), receiver, key);
|
|
10945
11634
|
}
|
|
10946
|
-
return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
|
11635
|
+
return new EmptyExpr$1(this.span(start), this.sourceSpan(start));
|
|
10947
11636
|
});
|
|
10948
11637
|
}
|
|
10949
11638
|
/**
|
|
@@ -11238,6 +11927,39 @@ class Comment {
|
|
|
11238
11927
|
return visitor.visitComment(this, context);
|
|
11239
11928
|
}
|
|
11240
11929
|
}
|
|
11930
|
+
class BlockGroup {
|
|
11931
|
+
constructor(blocks, sourceSpan, startSourceSpan, endSourceSpan = null) {
|
|
11932
|
+
this.blocks = blocks;
|
|
11933
|
+
this.sourceSpan = sourceSpan;
|
|
11934
|
+
this.startSourceSpan = startSourceSpan;
|
|
11935
|
+
this.endSourceSpan = endSourceSpan;
|
|
11936
|
+
}
|
|
11937
|
+
visit(visitor, context) {
|
|
11938
|
+
return visitor.visitBlockGroup(this, context);
|
|
11939
|
+
}
|
|
11940
|
+
}
|
|
11941
|
+
class Block {
|
|
11942
|
+
constructor(name, parameters, children, sourceSpan, startSourceSpan, endSourceSpan = null) {
|
|
11943
|
+
this.name = name;
|
|
11944
|
+
this.parameters = parameters;
|
|
11945
|
+
this.children = children;
|
|
11946
|
+
this.sourceSpan = sourceSpan;
|
|
11947
|
+
this.startSourceSpan = startSourceSpan;
|
|
11948
|
+
this.endSourceSpan = endSourceSpan;
|
|
11949
|
+
}
|
|
11950
|
+
visit(visitor, context) {
|
|
11951
|
+
return visitor.visitBlock(this, context);
|
|
11952
|
+
}
|
|
11953
|
+
}
|
|
11954
|
+
class BlockParameter {
|
|
11955
|
+
constructor(expression, sourceSpan) {
|
|
11956
|
+
this.expression = expression;
|
|
11957
|
+
this.sourceSpan = sourceSpan;
|
|
11958
|
+
}
|
|
11959
|
+
visit(visitor, context) {
|
|
11960
|
+
return visitor.visitBlockParameter(this, context);
|
|
11961
|
+
}
|
|
11962
|
+
}
|
|
11241
11963
|
function visitAll(visitor, nodes, context = null) {
|
|
11242
11964
|
const result = [];
|
|
11243
11965
|
const visit = visitor.visit ?
|
|
@@ -11268,6 +11990,18 @@ class RecursiveVisitor {
|
|
|
11268
11990
|
});
|
|
11269
11991
|
}
|
|
11270
11992
|
visitExpansionCase(ast, context) { }
|
|
11993
|
+
visitBlockGroup(ast, context) {
|
|
11994
|
+
this.visitChildren(context, visit => {
|
|
11995
|
+
visit(ast.blocks);
|
|
11996
|
+
});
|
|
11997
|
+
}
|
|
11998
|
+
visitBlock(block, context) {
|
|
11999
|
+
this.visitChildren(context, visit => {
|
|
12000
|
+
visit(block.parameters);
|
|
12001
|
+
visit(block.children);
|
|
12002
|
+
});
|
|
12003
|
+
}
|
|
12004
|
+
visitBlockParameter(ast, context) { }
|
|
11271
12005
|
visitChildren(context, cb) {
|
|
11272
12006
|
let results = [];
|
|
11273
12007
|
let t = this;
|
|
@@ -14020,8 +14754,8 @@ class _Tokenizer {
|
|
|
14020
14754
|
this._cursor = options.escapedString ? new EscapedCharacterCursor(_file, range) :
|
|
14021
14755
|
new PlainCharacterCursor(_file, range);
|
|
14022
14756
|
this._preserveLineEndings = options.preserveLineEndings || false;
|
|
14023
|
-
this._escapedString = options.escapedString || false;
|
|
14024
14757
|
this._i18nNormalizeLineEndingsInICUs = options.i18nNormalizeLineEndingsInICUs || false;
|
|
14758
|
+
this._tokenizeBlocks = options.tokenizeBlocks || false;
|
|
14025
14759
|
try {
|
|
14026
14760
|
this._cursor.init();
|
|
14027
14761
|
}
|
|
@@ -14062,6 +14796,15 @@ class _Tokenizer {
|
|
|
14062
14796
|
this._consumeTagOpen(start);
|
|
14063
14797
|
}
|
|
14064
14798
|
}
|
|
14799
|
+
else if (this._tokenizeBlocks && this._attemptStr('{#')) {
|
|
14800
|
+
this._consumeBlockGroupOpen(start);
|
|
14801
|
+
}
|
|
14802
|
+
else if (this._tokenizeBlocks && this._attemptStr('{/')) {
|
|
14803
|
+
this._consumeBlockGroupClose(start);
|
|
14804
|
+
}
|
|
14805
|
+
else if (this._tokenizeBlocks && this._attemptStr('{:')) {
|
|
14806
|
+
this._consumeBlock(start);
|
|
14807
|
+
}
|
|
14065
14808
|
else if (!(this._tokenizeIcu && this._tokenizeExpansionForm())) {
|
|
14066
14809
|
// In (possibly interpolated) text the end of the text is given by `isTextEnd()`, while
|
|
14067
14810
|
// the premature end of an interpolation is given by the start of a new HTML element.
|
|
@@ -14075,6 +14818,75 @@ class _Tokenizer {
|
|
|
14075
14818
|
this._beginToken(24 /* TokenType.EOF */);
|
|
14076
14819
|
this._endToken([]);
|
|
14077
14820
|
}
|
|
14821
|
+
_consumeBlockGroupOpen(start) {
|
|
14822
|
+
this._beginToken(25 /* TokenType.BLOCK_GROUP_OPEN_START */, start);
|
|
14823
|
+
const nameCursor = this._cursor.clone();
|
|
14824
|
+
this._attemptCharCodeUntilFn(code => !isBlockNameChar(code));
|
|
14825
|
+
this._endToken([this._cursor.getChars(nameCursor)]);
|
|
14826
|
+
this._consumeBlockParameters();
|
|
14827
|
+
this._beginToken(26 /* TokenType.BLOCK_GROUP_OPEN_END */);
|
|
14828
|
+
this._requireCharCode($RBRACE);
|
|
14829
|
+
this._endToken([]);
|
|
14830
|
+
}
|
|
14831
|
+
_consumeBlockGroupClose(start) {
|
|
14832
|
+
this._beginToken(27 /* TokenType.BLOCK_GROUP_CLOSE */, start);
|
|
14833
|
+
const nameCursor = this._cursor.clone();
|
|
14834
|
+
this._attemptCharCodeUntilFn(code => !isBlockNameChar(code));
|
|
14835
|
+
const name = this._cursor.getChars(nameCursor);
|
|
14836
|
+
this._requireCharCode($RBRACE);
|
|
14837
|
+
this._endToken([name]);
|
|
14838
|
+
}
|
|
14839
|
+
_consumeBlock(start) {
|
|
14840
|
+
this._beginToken(29 /* TokenType.BLOCK_OPEN_START */, start);
|
|
14841
|
+
const nameCursor = this._cursor.clone();
|
|
14842
|
+
this._attemptCharCodeUntilFn(code => !isBlockNameChar(code));
|
|
14843
|
+
this._endToken([this._cursor.getChars(nameCursor)]);
|
|
14844
|
+
this._consumeBlockParameters();
|
|
14845
|
+
this._beginToken(30 /* TokenType.BLOCK_OPEN_END */);
|
|
14846
|
+
this._requireCharCode($RBRACE);
|
|
14847
|
+
this._endToken([]);
|
|
14848
|
+
}
|
|
14849
|
+
_consumeBlockParameters() {
|
|
14850
|
+
// Trim the whitespace until the first parameter.
|
|
14851
|
+
this._attemptCharCodeUntilFn(isBlockParameterChar);
|
|
14852
|
+
while (this._cursor.peek() !== $RBRACE && this._cursor.peek() !== $EOF) {
|
|
14853
|
+
this._beginToken(28 /* TokenType.BLOCK_PARAMETER */);
|
|
14854
|
+
const start = this._cursor.clone();
|
|
14855
|
+
let inQuote = null;
|
|
14856
|
+
let openBraces = 0;
|
|
14857
|
+
// Consume the parameter until the next semicolon or brace.
|
|
14858
|
+
// Note that we skip over semicolons/braces inside of strings.
|
|
14859
|
+
while ((this._cursor.peek() !== $SEMICOLON && this._cursor.peek() !== $EOF) ||
|
|
14860
|
+
inQuote !== null) {
|
|
14861
|
+
const char = this._cursor.peek();
|
|
14862
|
+
// Skip to the next character if it was escaped.
|
|
14863
|
+
if (char === $BACKSLASH) {
|
|
14864
|
+
this._cursor.advance();
|
|
14865
|
+
}
|
|
14866
|
+
else if (char === inQuote) {
|
|
14867
|
+
inQuote = null;
|
|
14868
|
+
}
|
|
14869
|
+
else if (inQuote === null && isQuote(char)) {
|
|
14870
|
+
inQuote = char;
|
|
14871
|
+
}
|
|
14872
|
+
else if (char === $LBRACE && inQuote === null) {
|
|
14873
|
+
openBraces++;
|
|
14874
|
+
}
|
|
14875
|
+
else if (char === $RBRACE && inQuote === null) {
|
|
14876
|
+
if (openBraces === 0) {
|
|
14877
|
+
break;
|
|
14878
|
+
}
|
|
14879
|
+
else if (openBraces > 0) {
|
|
14880
|
+
openBraces--;
|
|
14881
|
+
}
|
|
14882
|
+
}
|
|
14883
|
+
this._cursor.advance();
|
|
14884
|
+
}
|
|
14885
|
+
this._endToken([this._cursor.getChars(start)]);
|
|
14886
|
+
// Skip to the next parameter.
|
|
14887
|
+
this._attemptCharCodeUntilFn(isBlockParameterChar);
|
|
14888
|
+
}
|
|
14889
|
+
}
|
|
14078
14890
|
/**
|
|
14079
14891
|
* @returns whether an ICU token has been created
|
|
14080
14892
|
* @internal
|
|
@@ -14596,7 +15408,7 @@ class _Tokenizer {
|
|
|
14596
15408
|
return this._processCarriageReturns(end.getChars(start));
|
|
14597
15409
|
}
|
|
14598
15410
|
_isTextEnd() {
|
|
14599
|
-
if (this._isTagStart() || this._cursor.peek() === $EOF) {
|
|
15411
|
+
if (this._isTagStart() || this._isBlockStart() || this._cursor.peek() === $EOF) {
|
|
14600
15412
|
return true;
|
|
14601
15413
|
}
|
|
14602
15414
|
if (this._tokenizeIcu && !this._inInterpolation) {
|
|
@@ -14629,6 +15441,23 @@ class _Tokenizer {
|
|
|
14629
15441
|
}
|
|
14630
15442
|
return false;
|
|
14631
15443
|
}
|
|
15444
|
+
_isBlockStart() {
|
|
15445
|
+
if (this._tokenizeBlocks && this._cursor.peek() === $LBRACE) {
|
|
15446
|
+
const tmp = this._cursor.clone();
|
|
15447
|
+
// Check that the cursor is on a `{#`, `{/` or `{:`.
|
|
15448
|
+
tmp.advance();
|
|
15449
|
+
const next = tmp.peek();
|
|
15450
|
+
if (next !== $BANG && next !== $SLASH && next !== $COLON) {
|
|
15451
|
+
return false;
|
|
15452
|
+
}
|
|
15453
|
+
// If it is, also verify that the next character is a valid block identifier.
|
|
15454
|
+
tmp.advance();
|
|
15455
|
+
if (isBlockNameChar(tmp.peek())) {
|
|
15456
|
+
return true;
|
|
15457
|
+
}
|
|
15458
|
+
}
|
|
15459
|
+
return false;
|
|
15460
|
+
}
|
|
14632
15461
|
_readUntil(char) {
|
|
14633
15462
|
const start = this._cursor.clone();
|
|
14634
15463
|
this._attemptUntilChar(char);
|
|
@@ -14684,6 +15513,12 @@ function compareCharCodeCaseInsensitive(code1, code2) {
|
|
|
14684
15513
|
function toUpperCaseCharCode(code) {
|
|
14685
15514
|
return code >= $a && code <= $z ? code - $a + $A : code;
|
|
14686
15515
|
}
|
|
15516
|
+
function isBlockNameChar(code) {
|
|
15517
|
+
return isAsciiLetter(code) || isDigit(code) || code === $_;
|
|
15518
|
+
}
|
|
15519
|
+
function isBlockParameterChar(code) {
|
|
15520
|
+
return code !== $SEMICOLON && isNotWhitespace(code);
|
|
15521
|
+
}
|
|
14687
15522
|
function mergeTextTokens(srcTokens) {
|
|
14688
15523
|
const dstTokens = [];
|
|
14689
15524
|
let lastDstToken = undefined;
|
|
@@ -14971,7 +15806,7 @@ class _TreeBuilder {
|
|
|
14971
15806
|
this.tokens = tokens;
|
|
14972
15807
|
this.getTagDefinition = getTagDefinition;
|
|
14973
15808
|
this._index = -1;
|
|
14974
|
-
this.
|
|
15809
|
+
this._containerStack = [];
|
|
14975
15810
|
this.rootNodes = [];
|
|
14976
15811
|
this.errors = [];
|
|
14977
15812
|
this._advance();
|
|
@@ -15001,6 +15836,18 @@ class _TreeBuilder {
|
|
|
15001
15836
|
else if (this._peek.type === 19 /* TokenType.EXPANSION_FORM_START */) {
|
|
15002
15837
|
this._consumeExpansion(this._advance());
|
|
15003
15838
|
}
|
|
15839
|
+
else if (this._peek.type === 25 /* TokenType.BLOCK_GROUP_OPEN_START */) {
|
|
15840
|
+
this._closeVoidElement();
|
|
15841
|
+
this._consumeBlockGroupOpen(this._advance());
|
|
15842
|
+
}
|
|
15843
|
+
else if (this._peek.type === 29 /* TokenType.BLOCK_OPEN_START */) {
|
|
15844
|
+
this._closeVoidElement();
|
|
15845
|
+
this._consumeBlock(this._advance(), 30 /* TokenType.BLOCK_OPEN_END */);
|
|
15846
|
+
}
|
|
15847
|
+
else if (this._peek.type === 27 /* TokenType.BLOCK_GROUP_CLOSE */) {
|
|
15848
|
+
this._closeVoidElement();
|
|
15849
|
+
this._consumeBlockGroupClose(this._advance());
|
|
15850
|
+
}
|
|
15004
15851
|
else {
|
|
15005
15852
|
// Skip all other tokens...
|
|
15006
15853
|
this._advance();
|
|
@@ -15028,9 +15875,12 @@ class _TreeBuilder {
|
|
|
15028
15875
|
}
|
|
15029
15876
|
_consumeComment(token) {
|
|
15030
15877
|
const text = this._advanceIf(7 /* TokenType.RAW_TEXT */);
|
|
15031
|
-
this._advanceIf(11 /* TokenType.COMMENT_END */);
|
|
15878
|
+
const endToken = this._advanceIf(11 /* TokenType.COMMENT_END */);
|
|
15032
15879
|
const value = text != null ? text.parts[0].trim() : null;
|
|
15033
|
-
|
|
15880
|
+
const sourceSpan = endToken == null ?
|
|
15881
|
+
token.sourceSpan :
|
|
15882
|
+
new ParseSourceSpan(token.sourceSpan.start, endToken.sourceSpan.end, token.sourceSpan.fullStart);
|
|
15883
|
+
this._addToParent(new Comment(value, sourceSpan));
|
|
15034
15884
|
}
|
|
15035
15885
|
_consumeExpansion(token) {
|
|
15036
15886
|
const switchValue = this._advance();
|
|
@@ -15117,7 +15967,12 @@ class _TreeBuilder {
|
|
|
15117
15967
|
const startSpan = token.sourceSpan;
|
|
15118
15968
|
let text = token.parts[0];
|
|
15119
15969
|
if (text.length > 0 && text[0] === '\n') {
|
|
15120
|
-
const parent = this.
|
|
15970
|
+
const parent = this._getContainer();
|
|
15971
|
+
// This is unlikely to happen, but we have an assertion just in case.
|
|
15972
|
+
if (parent instanceof BlockGroup) {
|
|
15973
|
+
this.errors.push(TreeError.create(null, startSpan, 'Text cannot be placed directly inside of a block group.'));
|
|
15974
|
+
return null;
|
|
15975
|
+
}
|
|
15121
15976
|
if (parent != null && parent.children.length === 0 &&
|
|
15122
15977
|
this.getTagDefinition(parent.name).ignoreFirstLf) {
|
|
15123
15978
|
text = text.substring(1);
|
|
@@ -15148,9 +16003,9 @@ class _TreeBuilder {
|
|
|
15148
16003
|
}
|
|
15149
16004
|
}
|
|
15150
16005
|
_closeVoidElement() {
|
|
15151
|
-
const el = this.
|
|
15152
|
-
if (el && this.getTagDefinition(el.name).isVoid) {
|
|
15153
|
-
this.
|
|
16006
|
+
const el = this._getContainer();
|
|
16007
|
+
if (el instanceof Element && this.getTagDefinition(el.name).isVoid) {
|
|
16008
|
+
this._containerStack.pop();
|
|
15154
16009
|
}
|
|
15155
16010
|
}
|
|
15156
16011
|
_consumeStartTag(startTagToken) {
|
|
@@ -15159,7 +16014,7 @@ class _TreeBuilder {
|
|
|
15159
16014
|
while (this._peek.type === 14 /* TokenType.ATTR_NAME */) {
|
|
15160
16015
|
attrs.push(this._consumeAttr(this._advance()));
|
|
15161
16016
|
}
|
|
15162
|
-
const fullName = this._getElementFullName(prefix, name, this.
|
|
16017
|
+
const fullName = this._getElementFullName(prefix, name, this._getClosestParentElement());
|
|
15163
16018
|
let selfClosing = false;
|
|
15164
16019
|
// Note: There could have been a tokenizer error
|
|
15165
16020
|
// so that we don't get a token for the end tag...
|
|
@@ -15180,33 +16035,34 @@ class _TreeBuilder {
|
|
|
15180
16035
|
// Create a separate `startSpan` because `span` will be modified when there is an `end` span.
|
|
15181
16036
|
const startSpan = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
|
|
15182
16037
|
const el = new Element(fullName, attrs, [], span, startSpan, undefined);
|
|
15183
|
-
this.
|
|
16038
|
+
const parentEl = this._getContainer();
|
|
16039
|
+
this._pushContainer(el, parentEl instanceof Element &&
|
|
16040
|
+
this.getTagDefinition(parentEl.name).isClosedByChild(el.name));
|
|
15184
16041
|
if (selfClosing) {
|
|
15185
16042
|
// Elements that are self-closed have their `endSourceSpan` set to the full span, as the
|
|
15186
16043
|
// element start tag also represents the end tag.
|
|
15187
|
-
this.
|
|
16044
|
+
this._popContainer(fullName, Element, span);
|
|
15188
16045
|
}
|
|
15189
16046
|
else if (startTagToken.type === 4 /* TokenType.INCOMPLETE_TAG_OPEN */) {
|
|
15190
16047
|
// We already know the opening tag is not complete, so it is unlikely it has a corresponding
|
|
15191
16048
|
// close tag. Let's optimistically parse it as a full element and emit an error.
|
|
15192
|
-
this.
|
|
16049
|
+
this._popContainer(fullName, Element, null);
|
|
15193
16050
|
this.errors.push(TreeError.create(fullName, span, `Opening tag "${fullName}" not terminated.`));
|
|
15194
16051
|
}
|
|
15195
16052
|
}
|
|
15196
|
-
|
|
15197
|
-
|
|
15198
|
-
|
|
15199
|
-
this._elementStack.pop();
|
|
16053
|
+
_pushContainer(node, isClosedByChild) {
|
|
16054
|
+
if (isClosedByChild) {
|
|
16055
|
+
this._containerStack.pop();
|
|
15200
16056
|
}
|
|
15201
|
-
this._addToParent(
|
|
15202
|
-
this.
|
|
16057
|
+
this._addToParent(node);
|
|
16058
|
+
this._containerStack.push(node);
|
|
15203
16059
|
}
|
|
15204
16060
|
_consumeEndTag(endTagToken) {
|
|
15205
|
-
const fullName = this._getElementFullName(endTagToken.parts[0], endTagToken.parts[1], this.
|
|
16061
|
+
const fullName = this._getElementFullName(endTagToken.parts[0], endTagToken.parts[1], this._getClosestParentElement());
|
|
15206
16062
|
if (this.getTagDefinition(fullName).isVoid) {
|
|
15207
16063
|
this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, `Void elements do not have end tags "${endTagToken.parts[1]}"`));
|
|
15208
16064
|
}
|
|
15209
|
-
else if (!this.
|
|
16065
|
+
else if (!this._popContainer(fullName, Element, endTagToken.sourceSpan)) {
|
|
15210
16066
|
const errMsg = `Unexpected closing tag "${fullName}". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags`;
|
|
15211
16067
|
this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, errMsg));
|
|
15212
16068
|
}
|
|
@@ -15217,20 +16073,23 @@ class _TreeBuilder {
|
|
|
15217
16073
|
* not have a closing tag (for example, this happens when an incomplete
|
|
15218
16074
|
* opening tag is recovered).
|
|
15219
16075
|
*/
|
|
15220
|
-
|
|
16076
|
+
_popContainer(fullName, expectedType, endSourceSpan) {
|
|
15221
16077
|
let unexpectedCloseTagDetected = false;
|
|
15222
|
-
for (let stackIndex = this.
|
|
15223
|
-
const
|
|
15224
|
-
|
|
16078
|
+
for (let stackIndex = this._containerStack.length - 1; stackIndex >= 0; stackIndex--) {
|
|
16079
|
+
const node = this._containerStack[stackIndex];
|
|
16080
|
+
const name = node instanceof BlockGroup ? node.blocks[0]?.name : node.name;
|
|
16081
|
+
if (name === fullName && node instanceof expectedType) {
|
|
15225
16082
|
// Record the parse span with the element that is being closed. Any elements that are
|
|
15226
16083
|
// removed from the element stack at this point are closed implicitly, so they won't get
|
|
15227
16084
|
// an end source span (as there is no explicit closing element).
|
|
15228
|
-
|
|
15229
|
-
|
|
15230
|
-
this.
|
|
16085
|
+
node.endSourceSpan = endSourceSpan;
|
|
16086
|
+
node.sourceSpan.end = endSourceSpan !== null ? endSourceSpan.end : node.sourceSpan.end;
|
|
16087
|
+
this._containerStack.splice(stackIndex, this._containerStack.length - stackIndex);
|
|
15231
16088
|
return !unexpectedCloseTagDetected;
|
|
15232
16089
|
}
|
|
15233
|
-
|
|
16090
|
+
// Blocks are self-closing while block groups and (most times) elements are not.
|
|
16091
|
+
if (node instanceof BlockGroup ||
|
|
16092
|
+
node instanceof Element && !this.getTagDefinition(node.name).closedByParent) {
|
|
15234
16093
|
// Note that we encountered an unexpected close tag but continue processing the element
|
|
15235
16094
|
// stack so we can assign an `endSourceSpan` if there is a corresponding start tag for this
|
|
15236
16095
|
// end tag in the stack.
|
|
@@ -15289,16 +16148,92 @@ class _TreeBuilder {
|
|
|
15289
16148
|
new ParseSourceSpan(valueStartSpan.start, valueEnd, valueStartSpan.fullStart);
|
|
15290
16149
|
return new Attribute(fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, attrEnd, attrName.sourceSpan.fullStart), attrName.sourceSpan, valueSpan, valueTokens.length > 0 ? valueTokens : undefined, undefined);
|
|
15291
16150
|
}
|
|
15292
|
-
|
|
15293
|
-
|
|
16151
|
+
_consumeBlockGroupOpen(token) {
|
|
16152
|
+
const end = this._peek.sourceSpan.fullStart;
|
|
16153
|
+
const span = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
|
|
16154
|
+
// Create a separate `startSpan` because `span` will be modified when there is an `end` span.
|
|
16155
|
+
const startSpan = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
|
|
16156
|
+
const blockGroup = new BlockGroup([], span, startSpan, null);
|
|
16157
|
+
this._pushContainer(blockGroup, false);
|
|
16158
|
+
const implicitBlock = this._consumeBlock(token, 26 /* TokenType.BLOCK_GROUP_OPEN_END */);
|
|
16159
|
+
// Block parameters are consumed as a part of the implicit block so we need to expand the
|
|
16160
|
+
// start source span once the block is parsed to include the full opening tag.
|
|
16161
|
+
startSpan.end = implicitBlock.startSourceSpan.end;
|
|
16162
|
+
}
|
|
16163
|
+
_consumeBlock(token, closeToken) {
|
|
16164
|
+
// The start of a block implicitly closes the previous block.
|
|
16165
|
+
this._conditionallyClosePreviousBlock();
|
|
16166
|
+
const parameters = [];
|
|
16167
|
+
while (this._peek.type === 28 /* TokenType.BLOCK_PARAMETER */) {
|
|
16168
|
+
const paramToken = this._advance();
|
|
16169
|
+
parameters.push(new BlockParameter(paramToken.parts[0], paramToken.sourceSpan));
|
|
16170
|
+
}
|
|
16171
|
+
if (this._peek.type === closeToken) {
|
|
16172
|
+
this._advance();
|
|
16173
|
+
}
|
|
16174
|
+
const end = this._peek.sourceSpan.fullStart;
|
|
16175
|
+
const span = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
|
|
16176
|
+
// Create a separate `startSpan` because `span` will be modified when there is an `end` span.
|
|
16177
|
+
const startSpan = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
|
|
16178
|
+
const block = new Block(token.parts[0], parameters, [], span, startSpan);
|
|
16179
|
+
const parent = this._getContainer();
|
|
16180
|
+
if (!(parent instanceof BlockGroup)) {
|
|
16181
|
+
this.errors.push(TreeError.create(block.name, block.sourceSpan, 'Blocks can only be placed inside of block groups.'));
|
|
16182
|
+
}
|
|
16183
|
+
else {
|
|
16184
|
+
parent.blocks.push(block);
|
|
16185
|
+
this._containerStack.push(block);
|
|
16186
|
+
}
|
|
16187
|
+
return block;
|
|
16188
|
+
}
|
|
16189
|
+
_consumeBlockGroupClose(token) {
|
|
16190
|
+
const name = token.parts[0];
|
|
16191
|
+
const previousContainer = this._getContainer();
|
|
16192
|
+
// Blocks are implcitly closed by the block group.
|
|
16193
|
+
this._conditionallyClosePreviousBlock();
|
|
16194
|
+
if (!this._popContainer(name, BlockGroup, token.sourceSpan)) {
|
|
16195
|
+
const context = previousContainer instanceof Element ?
|
|
16196
|
+
`There is an unclosed "${previousContainer.name}" HTML tag named that may have to be closed first.` :
|
|
16197
|
+
`The block may have been closed earlier.`;
|
|
16198
|
+
this.errors.push(TreeError.create(name, token.sourceSpan, `Unexpected closing block "${name}". ${context}`));
|
|
16199
|
+
}
|
|
16200
|
+
}
|
|
16201
|
+
_conditionallyClosePreviousBlock() {
|
|
16202
|
+
const container = this._getContainer();
|
|
16203
|
+
if (container instanceof Block) {
|
|
16204
|
+
// Blocks don't have an explicit closing tag, they're closed either by the next block or
|
|
16205
|
+
// the end of the block group. Infer the end span from the last child node.
|
|
16206
|
+
const lastChild = container.children.length ? container.children[container.children.length - 1] : null;
|
|
16207
|
+
const endSpan = lastChild === null ?
|
|
16208
|
+
null :
|
|
16209
|
+
new ParseSourceSpan(lastChild.sourceSpan.end, lastChild.sourceSpan.end);
|
|
16210
|
+
this._popContainer(container.name, Block, endSpan);
|
|
16211
|
+
}
|
|
16212
|
+
}
|
|
16213
|
+
_getContainer() {
|
|
16214
|
+
return this._containerStack.length > 0 ? this._containerStack[this._containerStack.length - 1] :
|
|
16215
|
+
null;
|
|
16216
|
+
}
|
|
16217
|
+
_getClosestParentElement() {
|
|
16218
|
+
for (let i = this._containerStack.length - 1; i > -1; i--) {
|
|
16219
|
+
if (this._containerStack[i] instanceof Element) {
|
|
16220
|
+
return this._containerStack[i];
|
|
16221
|
+
}
|
|
16222
|
+
}
|
|
16223
|
+
return null;
|
|
15294
16224
|
}
|
|
15295
16225
|
_addToParent(node) {
|
|
15296
|
-
const parent = this.
|
|
15297
|
-
if (parent
|
|
15298
|
-
|
|
16226
|
+
const parent = this._getContainer();
|
|
16227
|
+
if (parent === null) {
|
|
16228
|
+
this.rootNodes.push(node);
|
|
16229
|
+
}
|
|
16230
|
+
else if (parent instanceof BlockGroup) {
|
|
16231
|
+
// Due to how parsing is set up, we're unlikely to hit this code path, but we
|
|
16232
|
+
// have the assertion here just in case and to satisfy the type checker.
|
|
16233
|
+
this.errors.push(TreeError.create(null, node.sourceSpan, 'Block groups can only contain blocks.'));
|
|
15299
16234
|
}
|
|
15300
16235
|
else {
|
|
15301
|
-
|
|
16236
|
+
parent.children.push(node);
|
|
15302
16237
|
}
|
|
15303
16238
|
}
|
|
15304
16239
|
_getElementFullName(prefix, localName, parentElement) {
|
|
@@ -15412,6 +16347,15 @@ class WhitespaceVisitor {
|
|
|
15412
16347
|
visitExpansionCase(expansionCase, context) {
|
|
15413
16348
|
return expansionCase;
|
|
15414
16349
|
}
|
|
16350
|
+
visitBlockGroup(group, context) {
|
|
16351
|
+
return new BlockGroup(visitAllWithSiblings(this, group.blocks), group.sourceSpan, group.startSourceSpan, group.endSourceSpan);
|
|
16352
|
+
}
|
|
16353
|
+
visitBlock(block, context) {
|
|
16354
|
+
return new Block(block.name, block.parameters, visitAllWithSiblings(this, block.children), block.sourceSpan, block.startSourceSpan);
|
|
16355
|
+
}
|
|
16356
|
+
visitBlockParameter(parameter, context) {
|
|
16357
|
+
return parameter;
|
|
16358
|
+
}
|
|
15415
16359
|
}
|
|
15416
16360
|
function createWhitespaceProcessedTextToken({ type, parts, sourceSpan }) {
|
|
15417
16361
|
return { type, parts: [processWhitespace(parts[0])], sourceSpan };
|
|
@@ -15669,7 +16613,7 @@ class BindingParser {
|
|
|
15669
16613
|
this._parseAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps);
|
|
15670
16614
|
}
|
|
15671
16615
|
else {
|
|
15672
|
-
this._parsePropertyAst(name, this.
|
|
16616
|
+
this._parsePropertyAst(name, this.parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
|
|
15673
16617
|
}
|
|
15674
16618
|
}
|
|
15675
16619
|
parsePropertyInterpolation(name, value, sourceSpan, valueSpan, targetMatchableAttrs, targetProps, keySpan, interpolatedTokens) {
|
|
@@ -15691,11 +16635,11 @@ class BindingParser {
|
|
|
15691
16635
|
// This will occur when a @trigger is not paired with an expression.
|
|
15692
16636
|
// For animations it is valid to not have an expression since */void
|
|
15693
16637
|
// states will be applied by angular when the element is attached/detached
|
|
15694
|
-
const ast = this.
|
|
16638
|
+
const ast = this.parseBinding(expression || 'undefined', false, valueSpan || sourceSpan, absoluteOffset);
|
|
15695
16639
|
targetMatchableAttrs.push([name, ast.source]);
|
|
15696
16640
|
targetProps.push(new ParsedProperty(name, ast, exports.ParsedPropertyType.ANIMATION, sourceSpan, keySpan, valueSpan));
|
|
15697
16641
|
}
|
|
15698
|
-
|
|
16642
|
+
parseBinding(value, isHostBinding, sourceSpan, absoluteOffset) {
|
|
15699
16643
|
const sourceInfo = (sourceSpan && sourceSpan.start || '(unknown)').toString();
|
|
15700
16644
|
try {
|
|
15701
16645
|
const ast = isHostBinding ?
|
|
@@ -15814,7 +16758,7 @@ class BindingParser {
|
|
|
15814
16758
|
if (ast) {
|
|
15815
16759
|
this._reportExpressionParserErrors(ast.errors, sourceSpan);
|
|
15816
16760
|
}
|
|
15817
|
-
if (!ast || ast.ast instanceof EmptyExpr) {
|
|
16761
|
+
if (!ast || ast.ast instanceof EmptyExpr$1) {
|
|
15818
16762
|
this._reportError(`Empty expressions are not allowed`, sourceSpan);
|
|
15819
16763
|
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
|
|
15820
16764
|
}
|
|
@@ -15960,6 +16904,415 @@ function normalizeNgContentSelect(selectAttr) {
|
|
|
15960
16904
|
return selectAttr;
|
|
15961
16905
|
}
|
|
15962
16906
|
|
|
16907
|
+
/** Pattern for a timing value in a trigger. */
|
|
16908
|
+
const TIME_PATTERN = /^\d+(ms|s)?$/;
|
|
16909
|
+
/** Pattern for a separator between keywords in a trigger expression. */
|
|
16910
|
+
const SEPARATOR_PATTERN = /^\s$/;
|
|
16911
|
+
/** Pairs of characters that form syntax that is comma-delimited. */
|
|
16912
|
+
const COMMA_DELIMITED_SYNTAX = new Map([
|
|
16913
|
+
[$LBRACE, $RBRACE],
|
|
16914
|
+
[$LBRACKET, $RBRACKET],
|
|
16915
|
+
[$LPAREN, $RPAREN], // Function calls
|
|
16916
|
+
]);
|
|
16917
|
+
/** Possible types of `on` triggers. */
|
|
16918
|
+
var OnTriggerType;
|
|
16919
|
+
(function (OnTriggerType) {
|
|
16920
|
+
OnTriggerType["IDLE"] = "idle";
|
|
16921
|
+
OnTriggerType["TIMER"] = "timer";
|
|
16922
|
+
OnTriggerType["INTERACTION"] = "interaction";
|
|
16923
|
+
OnTriggerType["IMMEDIATE"] = "immediate";
|
|
16924
|
+
OnTriggerType["HOVER"] = "hover";
|
|
16925
|
+
OnTriggerType["VIEWPORT"] = "viewport";
|
|
16926
|
+
})(OnTriggerType || (OnTriggerType = {}));
|
|
16927
|
+
/** Parses a `when` deferred trigger. */
|
|
16928
|
+
function parseWhenTrigger({ expression, sourceSpan }, bindingParser, errors) {
|
|
16929
|
+
const whenIndex = expression.indexOf('when');
|
|
16930
|
+
// This is here just to be safe, we shouldn't enter this function
|
|
16931
|
+
// in the first place if a block doesn't have the "when" keyword.
|
|
16932
|
+
if (whenIndex === -1) {
|
|
16933
|
+
errors.push(new ParseError(sourceSpan, `Could not find "when" keyword in expression`));
|
|
16934
|
+
return null;
|
|
16935
|
+
}
|
|
16936
|
+
const start = getTriggerParametersStart(expression, whenIndex + 1);
|
|
16937
|
+
const parsed = bindingParser.parseBinding(expression.slice(start), false, sourceSpan, sourceSpan.start.offset + start);
|
|
16938
|
+
return new BoundDeferredTrigger(parsed, sourceSpan);
|
|
16939
|
+
}
|
|
16940
|
+
/** Parses an `on` trigger */
|
|
16941
|
+
function parseOnTrigger({ expression, sourceSpan }, errors) {
|
|
16942
|
+
const onIndex = expression.indexOf('on');
|
|
16943
|
+
// This is here just to be safe, we shouldn't enter this function
|
|
16944
|
+
// in the first place if a block doesn't have the "on" keyword.
|
|
16945
|
+
if (onIndex === -1) {
|
|
16946
|
+
errors.push(new ParseError(sourceSpan, `Could not find "on" keyword in expression`));
|
|
16947
|
+
return [];
|
|
16948
|
+
}
|
|
16949
|
+
const start = getTriggerParametersStart(expression, onIndex + 1);
|
|
16950
|
+
return new OnTriggerParser(expression, start, sourceSpan, errors).parse();
|
|
16951
|
+
}
|
|
16952
|
+
class OnTriggerParser {
|
|
16953
|
+
constructor(expression, start, span, errors) {
|
|
16954
|
+
this.expression = expression;
|
|
16955
|
+
this.start = start;
|
|
16956
|
+
this.span = span;
|
|
16957
|
+
this.errors = errors;
|
|
16958
|
+
this.index = 0;
|
|
16959
|
+
this.triggers = [];
|
|
16960
|
+
this.tokens = new Lexer().tokenize(expression.slice(start));
|
|
16961
|
+
}
|
|
16962
|
+
parse() {
|
|
16963
|
+
while (this.tokens.length > 0 && this.index < this.tokens.length) {
|
|
16964
|
+
const token = this.token();
|
|
16965
|
+
if (!token.isIdentifier()) {
|
|
16966
|
+
this.unexpectedToken(token);
|
|
16967
|
+
break;
|
|
16968
|
+
}
|
|
16969
|
+
// An identifier immediately followed by a comma or the end of
|
|
16970
|
+
// the expression cannot have parameters so we can exit early.
|
|
16971
|
+
if (this.isFollowedByOrLast($COMMA)) {
|
|
16972
|
+
this.consumeTrigger(token, []);
|
|
16973
|
+
this.advance();
|
|
16974
|
+
}
|
|
16975
|
+
else if (this.isFollowedByOrLast($LPAREN)) {
|
|
16976
|
+
this.advance(); // Advance to the opening paren.
|
|
16977
|
+
const prevErrors = this.errors.length;
|
|
16978
|
+
const parameters = this.consumeParameters();
|
|
16979
|
+
if (this.errors.length !== prevErrors) {
|
|
16980
|
+
break;
|
|
16981
|
+
}
|
|
16982
|
+
this.consumeTrigger(token, parameters);
|
|
16983
|
+
this.advance(); // Advance past the closing paren.
|
|
16984
|
+
}
|
|
16985
|
+
else if (this.index < this.tokens.length - 1) {
|
|
16986
|
+
this.unexpectedToken(this.tokens[this.index + 1]);
|
|
16987
|
+
}
|
|
16988
|
+
this.advance();
|
|
16989
|
+
}
|
|
16990
|
+
return this.triggers;
|
|
16991
|
+
}
|
|
16992
|
+
advance() {
|
|
16993
|
+
this.index++;
|
|
16994
|
+
}
|
|
16995
|
+
isFollowedByOrLast(char) {
|
|
16996
|
+
if (this.index === this.tokens.length - 1) {
|
|
16997
|
+
return true;
|
|
16998
|
+
}
|
|
16999
|
+
return this.tokens[this.index + 1].isCharacter(char);
|
|
17000
|
+
}
|
|
17001
|
+
token() {
|
|
17002
|
+
return this.tokens[Math.min(this.index, this.tokens.length - 1)];
|
|
17003
|
+
}
|
|
17004
|
+
consumeTrigger(identifier, parameters) {
|
|
17005
|
+
const startSpan = this.span.start.moveBy(this.start + identifier.index - this.tokens[0].index);
|
|
17006
|
+
const endSpan = startSpan.moveBy(this.token().end - identifier.index);
|
|
17007
|
+
const sourceSpan = new ParseSourceSpan(startSpan, endSpan);
|
|
17008
|
+
try {
|
|
17009
|
+
switch (identifier.toString()) {
|
|
17010
|
+
case OnTriggerType.IDLE:
|
|
17011
|
+
this.triggers.push(createIdleTrigger(parameters, sourceSpan));
|
|
17012
|
+
break;
|
|
17013
|
+
case OnTriggerType.TIMER:
|
|
17014
|
+
this.triggers.push(createTimerTrigger(parameters, sourceSpan));
|
|
17015
|
+
break;
|
|
17016
|
+
case OnTriggerType.INTERACTION:
|
|
17017
|
+
this.triggers.push(createInteractionTrigger(parameters, sourceSpan));
|
|
17018
|
+
break;
|
|
17019
|
+
case OnTriggerType.IMMEDIATE:
|
|
17020
|
+
this.triggers.push(createImmediateTrigger(parameters, sourceSpan));
|
|
17021
|
+
break;
|
|
17022
|
+
case OnTriggerType.HOVER:
|
|
17023
|
+
this.triggers.push(createHoverTrigger(parameters, sourceSpan));
|
|
17024
|
+
break;
|
|
17025
|
+
case OnTriggerType.VIEWPORT:
|
|
17026
|
+
this.triggers.push(createViewportTrigger(parameters, sourceSpan));
|
|
17027
|
+
break;
|
|
17028
|
+
default:
|
|
17029
|
+
throw new Error(`Unrecognized trigger type "${identifier}"`);
|
|
17030
|
+
}
|
|
17031
|
+
}
|
|
17032
|
+
catch (e) {
|
|
17033
|
+
this.error(identifier, e.message);
|
|
17034
|
+
}
|
|
17035
|
+
}
|
|
17036
|
+
consumeParameters() {
|
|
17037
|
+
const parameters = [];
|
|
17038
|
+
if (!this.token().isCharacter($LPAREN)) {
|
|
17039
|
+
this.unexpectedToken(this.token());
|
|
17040
|
+
return parameters;
|
|
17041
|
+
}
|
|
17042
|
+
this.advance();
|
|
17043
|
+
const commaDelimStack = [];
|
|
17044
|
+
let current = '';
|
|
17045
|
+
while (this.index < this.tokens.length) {
|
|
17046
|
+
const token = this.token();
|
|
17047
|
+
// Stop parsing if we've hit the end character and we're outside of a comma-delimited syntax.
|
|
17048
|
+
// Note that we don't need to account for strings here since the lexer already parsed them
|
|
17049
|
+
// into string tokens.
|
|
17050
|
+
if (token.isCharacter($RPAREN) && commaDelimStack.length === 0) {
|
|
17051
|
+
if (current.length) {
|
|
17052
|
+
parameters.push(current);
|
|
17053
|
+
}
|
|
17054
|
+
break;
|
|
17055
|
+
}
|
|
17056
|
+
// In the `on` microsyntax "top-level" commas (e.g. ones outside of an parameters) separate
|
|
17057
|
+
// the different triggers (e.g. `on idle,timer(500)`). This is problematic, because the
|
|
17058
|
+
// function-like syntax also implies that multiple parameters can be passed into the
|
|
17059
|
+
// individual trigger (e.g. `on foo(a, b)`). To avoid tripping up the parser with commas that
|
|
17060
|
+
// are part of other sorts of syntax (object literals, arrays), we treat anything inside
|
|
17061
|
+
// a comma-delimited syntax block as plain text.
|
|
17062
|
+
if (token.type === exports.TokenType.Character && COMMA_DELIMITED_SYNTAX.has(token.numValue)) {
|
|
17063
|
+
commaDelimStack.push(COMMA_DELIMITED_SYNTAX.get(token.numValue));
|
|
17064
|
+
}
|
|
17065
|
+
if (commaDelimStack.length > 0 &&
|
|
17066
|
+
token.isCharacter(commaDelimStack[commaDelimStack.length - 1])) {
|
|
17067
|
+
commaDelimStack.pop();
|
|
17068
|
+
}
|
|
17069
|
+
// If we hit a comma outside of a comma-delimited syntax, it means
|
|
17070
|
+
// that we're at the top level and we're starting a new parameter.
|
|
17071
|
+
if (commaDelimStack.length === 0 && token.isCharacter($COMMA) && current.length > 0) {
|
|
17072
|
+
parameters.push(current);
|
|
17073
|
+
current = '';
|
|
17074
|
+
this.advance();
|
|
17075
|
+
continue;
|
|
17076
|
+
}
|
|
17077
|
+
// Otherwise treat the token as a plain text character in the current parameter.
|
|
17078
|
+
current += this.tokenText();
|
|
17079
|
+
this.advance();
|
|
17080
|
+
}
|
|
17081
|
+
if (!this.token().isCharacter($RPAREN) || commaDelimStack.length > 0) {
|
|
17082
|
+
this.error(this.token(), 'Unexpected end of expression');
|
|
17083
|
+
}
|
|
17084
|
+
if (this.index < this.tokens.length - 1 &&
|
|
17085
|
+
!this.tokens[this.index + 1].isCharacter($COMMA)) {
|
|
17086
|
+
this.unexpectedToken(this.tokens[this.index + 1]);
|
|
17087
|
+
}
|
|
17088
|
+
return parameters;
|
|
17089
|
+
}
|
|
17090
|
+
tokenText() {
|
|
17091
|
+
// Tokens have a toString already which we could use, but for string tokens it omits the quotes.
|
|
17092
|
+
// Eventually we could expose this information on the token directly.
|
|
17093
|
+
return this.expression.slice(this.start + this.token().index, this.start + this.token().end);
|
|
17094
|
+
}
|
|
17095
|
+
error(token, message) {
|
|
17096
|
+
const newStart = this.span.start.moveBy(this.start + token.index);
|
|
17097
|
+
const newEnd = newStart.moveBy(token.end - token.index);
|
|
17098
|
+
this.errors.push(new ParseError(new ParseSourceSpan(newStart, newEnd), message));
|
|
17099
|
+
}
|
|
17100
|
+
unexpectedToken(token) {
|
|
17101
|
+
this.error(token, `Unexpected token "${token}"`);
|
|
17102
|
+
}
|
|
17103
|
+
}
|
|
17104
|
+
function createIdleTrigger(parameters, sourceSpan) {
|
|
17105
|
+
if (parameters.length > 0) {
|
|
17106
|
+
throw new Error(`"${OnTriggerType.IDLE}" trigger cannot have parameters`);
|
|
17107
|
+
}
|
|
17108
|
+
return new IdleDeferredTrigger(sourceSpan);
|
|
17109
|
+
}
|
|
17110
|
+
function createTimerTrigger(parameters, sourceSpan) {
|
|
17111
|
+
if (parameters.length !== 1) {
|
|
17112
|
+
throw new Error(`"${OnTriggerType.TIMER}" trigger must have exactly one parameter`);
|
|
17113
|
+
}
|
|
17114
|
+
const delay = parseDeferredTime(parameters[0]);
|
|
17115
|
+
if (delay === null) {
|
|
17116
|
+
throw new Error(`Could not parse time value of trigger "${OnTriggerType.TIMER}"`);
|
|
17117
|
+
}
|
|
17118
|
+
return new TimerDeferredTrigger(delay, sourceSpan);
|
|
17119
|
+
}
|
|
17120
|
+
function createInteractionTrigger(parameters, sourceSpan) {
|
|
17121
|
+
if (parameters.length > 1) {
|
|
17122
|
+
throw new Error(`"${OnTriggerType.INTERACTION}" trigger can only have zero or one parameters`);
|
|
17123
|
+
}
|
|
17124
|
+
return new InteractionDeferredTrigger(parameters[0] ?? null, sourceSpan);
|
|
17125
|
+
}
|
|
17126
|
+
function createImmediateTrigger(parameters, sourceSpan) {
|
|
17127
|
+
if (parameters.length > 0) {
|
|
17128
|
+
throw new Error(`"${OnTriggerType.IMMEDIATE}" trigger cannot have parameters`);
|
|
17129
|
+
}
|
|
17130
|
+
return new ImmediateDeferredTrigger(sourceSpan);
|
|
17131
|
+
}
|
|
17132
|
+
function createHoverTrigger(parameters, sourceSpan) {
|
|
17133
|
+
if (parameters.length > 0) {
|
|
17134
|
+
throw new Error(`"${OnTriggerType.HOVER}" trigger cannot have parameters`);
|
|
17135
|
+
}
|
|
17136
|
+
return new HoverDeferredTrigger(sourceSpan);
|
|
17137
|
+
}
|
|
17138
|
+
function createViewportTrigger(parameters, sourceSpan) {
|
|
17139
|
+
// TODO: the RFC has some more potential parameters for `viewport`.
|
|
17140
|
+
if (parameters.length > 1) {
|
|
17141
|
+
throw new Error(`"${OnTriggerType.VIEWPORT}" trigger can only have zero or one parameters`);
|
|
17142
|
+
}
|
|
17143
|
+
return new ViewportDeferredTrigger(parameters[0] ?? null, sourceSpan);
|
|
17144
|
+
}
|
|
17145
|
+
/** Gets the index within an expression at which the trigger parameters start. */
|
|
17146
|
+
function getTriggerParametersStart(value, startPosition = 0) {
|
|
17147
|
+
let hasFoundSeparator = false;
|
|
17148
|
+
for (let i = startPosition; i < value.length; i++) {
|
|
17149
|
+
if (SEPARATOR_PATTERN.test(value[i])) {
|
|
17150
|
+
hasFoundSeparator = true;
|
|
17151
|
+
}
|
|
17152
|
+
else if (hasFoundSeparator) {
|
|
17153
|
+
return i;
|
|
17154
|
+
}
|
|
17155
|
+
}
|
|
17156
|
+
return -1;
|
|
17157
|
+
}
|
|
17158
|
+
/**
|
|
17159
|
+
* Parses a time expression from a deferred trigger to
|
|
17160
|
+
* milliseconds. Returns null if it cannot be parsed.
|
|
17161
|
+
*/
|
|
17162
|
+
function parseDeferredTime(value) {
|
|
17163
|
+
const match = value.match(TIME_PATTERN);
|
|
17164
|
+
if (!match) {
|
|
17165
|
+
return null;
|
|
17166
|
+
}
|
|
17167
|
+
const [time, units] = match;
|
|
17168
|
+
return parseInt(time) * (units === 's' ? 1000 : 1);
|
|
17169
|
+
}
|
|
17170
|
+
|
|
17171
|
+
/** Pattern to identify a `prefetch when` trigger. */
|
|
17172
|
+
const PREFETCH_WHEN_PATTERN = /^prefetch\s+when\s/;
|
|
17173
|
+
/** Pattern to identify a `prefetch on` trigger. */
|
|
17174
|
+
const PREFETCH_ON_PATTERN = /^prefetch\s+on\s/;
|
|
17175
|
+
/** Pattern to identify a `minimum` parameter in a block. */
|
|
17176
|
+
const MINIMUM_PARAMETER_PATTERN = /^minimum\s/;
|
|
17177
|
+
/** Pattern to identify a `after` parameter in a block. */
|
|
17178
|
+
const AFTER_PARAMETER_PATTERN = /^after\s/;
|
|
17179
|
+
/** Pattern to identify a `when` parameter in a block. */
|
|
17180
|
+
const WHEN_PARAMETER_PATTERN = /^when\s/;
|
|
17181
|
+
/** Pattern to identify a `on` parameter in a block. */
|
|
17182
|
+
const ON_PARAMETER_PATTERN = /^on\s/;
|
|
17183
|
+
/** Possible types of secondary deferred blocks. */
|
|
17184
|
+
var SecondaryDeferredBlockType;
|
|
17185
|
+
(function (SecondaryDeferredBlockType) {
|
|
17186
|
+
SecondaryDeferredBlockType["PLACEHOLDER"] = "placeholder";
|
|
17187
|
+
SecondaryDeferredBlockType["LOADING"] = "loading";
|
|
17188
|
+
SecondaryDeferredBlockType["ERROR"] = "error";
|
|
17189
|
+
})(SecondaryDeferredBlockType || (SecondaryDeferredBlockType = {}));
|
|
17190
|
+
/** Creates a deferred block from an HTML AST node. */
|
|
17191
|
+
function createDeferredBlock(ast, visitor, bindingParser) {
|
|
17192
|
+
const errors = [];
|
|
17193
|
+
const [primaryBlock, ...secondaryBlocks] = ast.blocks;
|
|
17194
|
+
const { triggers, prefetchTriggers } = parsePrimaryTriggers(primaryBlock.parameters, bindingParser, errors);
|
|
17195
|
+
const { placeholder, loading, error } = parseSecondaryBlocks(secondaryBlocks, errors, visitor);
|
|
17196
|
+
return {
|
|
17197
|
+
node: new DeferredBlock(visitAll(visitor, primaryBlock.children), triggers, prefetchTriggers, placeholder, loading, error, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan),
|
|
17198
|
+
errors,
|
|
17199
|
+
};
|
|
17200
|
+
}
|
|
17201
|
+
function parseSecondaryBlocks(blocks, errors, visitor) {
|
|
17202
|
+
let placeholder = null;
|
|
17203
|
+
let loading = null;
|
|
17204
|
+
let error = null;
|
|
17205
|
+
for (const block of blocks) {
|
|
17206
|
+
try {
|
|
17207
|
+
switch (block.name) {
|
|
17208
|
+
case SecondaryDeferredBlockType.PLACEHOLDER:
|
|
17209
|
+
if (placeholder !== null) {
|
|
17210
|
+
errors.push(new ParseError(block.startSourceSpan, `"defer" block can only have one "${SecondaryDeferredBlockType.PLACEHOLDER}" block`));
|
|
17211
|
+
}
|
|
17212
|
+
else {
|
|
17213
|
+
placeholder = parsePlaceholderBlock(block, visitor);
|
|
17214
|
+
}
|
|
17215
|
+
break;
|
|
17216
|
+
case SecondaryDeferredBlockType.LOADING:
|
|
17217
|
+
if (loading !== null) {
|
|
17218
|
+
errors.push(new ParseError(block.startSourceSpan, `"defer" block can only have one "${SecondaryDeferredBlockType.LOADING}" block`));
|
|
17219
|
+
}
|
|
17220
|
+
else {
|
|
17221
|
+
loading = parseLoadingBlock(block, visitor);
|
|
17222
|
+
}
|
|
17223
|
+
break;
|
|
17224
|
+
case SecondaryDeferredBlockType.ERROR:
|
|
17225
|
+
if (error !== null) {
|
|
17226
|
+
errors.push(new ParseError(block.startSourceSpan, `"defer" block can only have one "${SecondaryDeferredBlockType.ERROR}" block`));
|
|
17227
|
+
}
|
|
17228
|
+
else {
|
|
17229
|
+
error = parseErrorBlock(block, visitor);
|
|
17230
|
+
}
|
|
17231
|
+
break;
|
|
17232
|
+
default:
|
|
17233
|
+
errors.push(new ParseError(block.startSourceSpan, `Unrecognized block "${block.name}"`));
|
|
17234
|
+
break;
|
|
17235
|
+
}
|
|
17236
|
+
}
|
|
17237
|
+
catch (e) {
|
|
17238
|
+
errors.push(new ParseError(block.startSourceSpan, e.message));
|
|
17239
|
+
}
|
|
17240
|
+
}
|
|
17241
|
+
return { placeholder, loading, error };
|
|
17242
|
+
}
|
|
17243
|
+
function parsePlaceholderBlock(ast, visitor) {
|
|
17244
|
+
let minimumTime = null;
|
|
17245
|
+
for (const param of ast.parameters) {
|
|
17246
|
+
if (MINIMUM_PARAMETER_PATTERN.test(param.expression)) {
|
|
17247
|
+
const parsedTime = parseDeferredTime(param.expression.slice(getTriggerParametersStart(param.expression)));
|
|
17248
|
+
if (parsedTime === null) {
|
|
17249
|
+
throw new Error(`Could not parse time value of parameter "minimum"`);
|
|
17250
|
+
}
|
|
17251
|
+
minimumTime = parsedTime;
|
|
17252
|
+
}
|
|
17253
|
+
else {
|
|
17254
|
+
throw new Error(`Unrecognized parameter in "${SecondaryDeferredBlockType.PLACEHOLDER}" block: "${param.expression}"`);
|
|
17255
|
+
}
|
|
17256
|
+
}
|
|
17257
|
+
return new DeferredBlockPlaceholder(visitAll(visitor, ast.children), minimumTime, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
17258
|
+
}
|
|
17259
|
+
function parseLoadingBlock(ast, visitor) {
|
|
17260
|
+
let afterTime = null;
|
|
17261
|
+
let minimumTime = null;
|
|
17262
|
+
for (const param of ast.parameters) {
|
|
17263
|
+
if (AFTER_PARAMETER_PATTERN.test(param.expression)) {
|
|
17264
|
+
const parsedTime = parseDeferredTime(param.expression.slice(getTriggerParametersStart(param.expression)));
|
|
17265
|
+
if (parsedTime === null) {
|
|
17266
|
+
throw new Error(`Could not parse time value of parameter "after"`);
|
|
17267
|
+
}
|
|
17268
|
+
afterTime = parsedTime;
|
|
17269
|
+
}
|
|
17270
|
+
else if (MINIMUM_PARAMETER_PATTERN.test(param.expression)) {
|
|
17271
|
+
const parsedTime = parseDeferredTime(param.expression.slice(getTriggerParametersStart(param.expression)));
|
|
17272
|
+
if (parsedTime === null) {
|
|
17273
|
+
throw new Error(`Could not parse time value of parameter "minimum"`);
|
|
17274
|
+
}
|
|
17275
|
+
minimumTime = parsedTime;
|
|
17276
|
+
}
|
|
17277
|
+
else {
|
|
17278
|
+
throw new Error(`Unrecognized parameter in "${SecondaryDeferredBlockType.LOADING}" block: "${param.expression}"`);
|
|
17279
|
+
}
|
|
17280
|
+
}
|
|
17281
|
+
return new DeferredBlockLoading(visitAll(visitor, ast.children), afterTime, minimumTime, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
17282
|
+
}
|
|
17283
|
+
function parseErrorBlock(ast, visitor) {
|
|
17284
|
+
if (ast.parameters.length > 0) {
|
|
17285
|
+
throw new Error(`"${SecondaryDeferredBlockType.ERROR}" block cannot have parameters`);
|
|
17286
|
+
}
|
|
17287
|
+
return new DeferredBlockError(visitAll(visitor, ast.children), ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
17288
|
+
}
|
|
17289
|
+
function parsePrimaryTriggers(params, bindingParser, errors) {
|
|
17290
|
+
const triggers = [];
|
|
17291
|
+
const prefetchTriggers = [];
|
|
17292
|
+
for (const param of params) {
|
|
17293
|
+
// The lexer ignores the leading spaces so we can assume
|
|
17294
|
+
// that the expression starts with a keyword.
|
|
17295
|
+
if (WHEN_PARAMETER_PATTERN.test(param.expression)) {
|
|
17296
|
+
const result = parseWhenTrigger(param, bindingParser, errors);
|
|
17297
|
+
result !== null && triggers.push(result);
|
|
17298
|
+
}
|
|
17299
|
+
else if (ON_PARAMETER_PATTERN.test(param.expression)) {
|
|
17300
|
+
triggers.push(...parseOnTrigger(param, errors));
|
|
17301
|
+
}
|
|
17302
|
+
else if (PREFETCH_WHEN_PATTERN.test(param.expression)) {
|
|
17303
|
+
const result = parseWhenTrigger(param, bindingParser, errors);
|
|
17304
|
+
result !== null && prefetchTriggers.push(result);
|
|
17305
|
+
}
|
|
17306
|
+
else if (PREFETCH_ON_PATTERN.test(param.expression)) {
|
|
17307
|
+
prefetchTriggers.push(...parseOnTrigger(param, errors));
|
|
17308
|
+
}
|
|
17309
|
+
else {
|
|
17310
|
+
errors.push(new ParseError(param.sourceSpan, 'Unrecognized trigger'));
|
|
17311
|
+
}
|
|
17312
|
+
}
|
|
17313
|
+
return { triggers, prefetchTriggers };
|
|
17314
|
+
}
|
|
17315
|
+
|
|
15963
17316
|
const BIND_NAME_REGEXP = /^(?:(bind-)|(let-)|(ref-|#)|(on-)|(bindon-)|(@))(.*)$/;
|
|
15964
17317
|
// Group 1 = "bind-"
|
|
15965
17318
|
const KW_BIND_IDX = 1;
|
|
@@ -16083,7 +17436,16 @@ class HtmlAstToIvyAst {
|
|
|
16083
17436
|
attributes.push(this.visitAttribute(attribute));
|
|
16084
17437
|
}
|
|
16085
17438
|
}
|
|
16086
|
-
|
|
17439
|
+
let children;
|
|
17440
|
+
if (preparsedElement.nonBindable) {
|
|
17441
|
+
// The `NonBindableVisitor` may need to return an array of nodes for block groups so we need
|
|
17442
|
+
// to flatten the array here. Avoid doing this for the `HtmlAstToIvyAst` since `flat` creates
|
|
17443
|
+
// a new array.
|
|
17444
|
+
children = visitAll(NON_BINDABLE_VISITOR, element.children).flat(Infinity);
|
|
17445
|
+
}
|
|
17446
|
+
else {
|
|
17447
|
+
children = visitAll(this, element.children);
|
|
17448
|
+
}
|
|
16087
17449
|
let parsedElement;
|
|
16088
17450
|
if (preparsedElement.type === PreparsedElementType.NG_CONTENT) {
|
|
16089
17451
|
// `<ng-content>`
|
|
@@ -16181,6 +17543,23 @@ class HtmlAstToIvyAst {
|
|
|
16181
17543
|
}
|
|
16182
17544
|
return null;
|
|
16183
17545
|
}
|
|
17546
|
+
visitBlockGroup(group, context) {
|
|
17547
|
+
const primaryBlock = group.blocks[0];
|
|
17548
|
+
// The HTML parser ensures that we don't hit this case, but we have an assertion just in case.
|
|
17549
|
+
if (!primaryBlock) {
|
|
17550
|
+
this.reportError('Block group must have at least one block.', group.sourceSpan);
|
|
17551
|
+
return null;
|
|
17552
|
+
}
|
|
17553
|
+
if (primaryBlock.name === 'defer' && this.options.enabledBlockTypes.has(primaryBlock.name)) {
|
|
17554
|
+
const { node, errors } = createDeferredBlock(group, this, this.bindingParser);
|
|
17555
|
+
this.errors.push(...errors);
|
|
17556
|
+
return node;
|
|
17557
|
+
}
|
|
17558
|
+
this.reportError(`Unrecognized block "${primaryBlock.name}".`, primaryBlock.sourceSpan);
|
|
17559
|
+
return null;
|
|
17560
|
+
}
|
|
17561
|
+
visitBlock(block, context) { }
|
|
17562
|
+
visitBlockParameter(parameter, context) { }
|
|
16184
17563
|
// convert view engine `ParsedProperty` to a format suitable for IVY
|
|
16185
17564
|
extractAttributes(elementName, properties, i18nPropsMeta) {
|
|
16186
17565
|
const bound = [];
|
|
@@ -16358,6 +17737,25 @@ class NonBindableVisitor {
|
|
|
16358
17737
|
visitExpansionCase(expansionCase) {
|
|
16359
17738
|
return null;
|
|
16360
17739
|
}
|
|
17740
|
+
visitBlockGroup(group, context) {
|
|
17741
|
+
const nodes = visitAll(this, group.blocks);
|
|
17742
|
+
// We only need to do the end tag since the start will be added as a part of the primary block.
|
|
17743
|
+
if (group.endSourceSpan !== null) {
|
|
17744
|
+
nodes.push(new Text$3(group.endSourceSpan.toString(), group.endSourceSpan));
|
|
17745
|
+
}
|
|
17746
|
+
return nodes;
|
|
17747
|
+
}
|
|
17748
|
+
visitBlock(block, context) {
|
|
17749
|
+
return [
|
|
17750
|
+
// In an ngNonBindable context we treat the opening/closing tags of block as plain text.
|
|
17751
|
+
// This is the as if the `tokenizeBlocks` option was disabled.
|
|
17752
|
+
new Text$3(block.startSourceSpan.toString(), block.startSourceSpan),
|
|
17753
|
+
...visitAll(this, block.children)
|
|
17754
|
+
];
|
|
17755
|
+
}
|
|
17756
|
+
visitBlockParameter(parameter, context) {
|
|
17757
|
+
return null;
|
|
17758
|
+
}
|
|
16361
17759
|
}
|
|
16362
17760
|
const NON_BINDABLE_VISITOR = new NonBindableVisitor();
|
|
16363
17761
|
function normalizeAttributeName(attrName) {
|
|
@@ -16805,6 +18203,17 @@ class _I18nVisitor {
|
|
|
16805
18203
|
visitExpansionCase(_icuCase, _context) {
|
|
16806
18204
|
throw new Error('Unreachable code');
|
|
16807
18205
|
}
|
|
18206
|
+
visitBlockGroup(group, context) {
|
|
18207
|
+
const children = visitAll(this, group.blocks, context);
|
|
18208
|
+
const node = new Container(children, group.sourceSpan);
|
|
18209
|
+
return context.visitNodeFn(group, node);
|
|
18210
|
+
}
|
|
18211
|
+
visitBlock(block, context) {
|
|
18212
|
+
const children = visitAll(this, block.children, context);
|
|
18213
|
+
const node = new Container(children, block.sourceSpan);
|
|
18214
|
+
return context.visitNodeFn(block, node);
|
|
18215
|
+
}
|
|
18216
|
+
visitBlockParameter(_parameter, _context) { }
|
|
16808
18217
|
/**
|
|
16809
18218
|
* Convert, text and interpolated tokens up into text and placeholder pieces.
|
|
16810
18219
|
*
|
|
@@ -17051,6 +18460,17 @@ class I18nMetaVisitor {
|
|
|
17051
18460
|
visitExpansionCase(expansionCase) {
|
|
17052
18461
|
return expansionCase;
|
|
17053
18462
|
}
|
|
18463
|
+
visitBlockGroup(group, context) {
|
|
18464
|
+
visitAll(this, group.blocks, context);
|
|
18465
|
+
return group;
|
|
18466
|
+
}
|
|
18467
|
+
visitBlock(block, context) {
|
|
18468
|
+
visitAll(this, block.children, context);
|
|
18469
|
+
return block;
|
|
18470
|
+
}
|
|
18471
|
+
visitBlockParameter(parameter, context) {
|
|
18472
|
+
return parameter;
|
|
18473
|
+
}
|
|
17054
18474
|
/**
|
|
17055
18475
|
* Parse the general form `meta` passed into extract the explicit metadata needed to create a
|
|
17056
18476
|
* `Message`.
|
|
@@ -17432,7 +18852,7 @@ function createComponentDefConsts() {
|
|
|
17432
18852
|
};
|
|
17433
18853
|
}
|
|
17434
18854
|
class TemplateDefinitionBuilder {
|
|
17435
|
-
constructor(constantPool, parentBindingScope, level = 0, contextName, i18nContext, templateIndex, templateName, _namespace, relativeContextFilePath, i18nUseExternalIds, _constants = createComponentDefConsts()) {
|
|
18855
|
+
constructor(constantPool, parentBindingScope, level = 0, contextName, i18nContext, templateIndex, templateName, _namespace, relativeContextFilePath, i18nUseExternalIds, deferBlocks, _constants = createComponentDefConsts()) {
|
|
17436
18856
|
this.constantPool = constantPool;
|
|
17437
18857
|
this.level = level;
|
|
17438
18858
|
this.contextName = contextName;
|
|
@@ -17441,6 +18861,7 @@ class TemplateDefinitionBuilder {
|
|
|
17441
18861
|
this.templateName = templateName;
|
|
17442
18862
|
this._namespace = _namespace;
|
|
17443
18863
|
this.i18nUseExternalIds = i18nUseExternalIds;
|
|
18864
|
+
this.deferBlocks = deferBlocks;
|
|
17444
18865
|
this._constants = _constants;
|
|
17445
18866
|
this._dataIndex = 0;
|
|
17446
18867
|
this._bindingContext = 0;
|
|
@@ -17643,7 +19064,7 @@ class TemplateDefinitionBuilder {
|
|
|
17643
19064
|
else {
|
|
17644
19065
|
const value = prop.value.visit(this._valueConverter);
|
|
17645
19066
|
this.allocateBindingSlots(value);
|
|
17646
|
-
if (value instanceof Interpolation) {
|
|
19067
|
+
if (value instanceof Interpolation$1) {
|
|
17647
19068
|
const { strings, expressions } = value;
|
|
17648
19069
|
const { id, bindings } = this.i18n;
|
|
17649
19070
|
const label = assembleI18nBoundString(strings, bindings.size, id);
|
|
@@ -17763,7 +19184,7 @@ class TemplateDefinitionBuilder {
|
|
|
17763
19184
|
const message = attr.i18n;
|
|
17764
19185
|
const converted = attr.value.visit(this._valueConverter);
|
|
17765
19186
|
this.allocateBindingSlots(converted);
|
|
17766
|
-
if (converted instanceof Interpolation) {
|
|
19187
|
+
if (converted instanceof Interpolation$1) {
|
|
17767
19188
|
const placeholders = assembleBoundTextPlaceholders(message);
|
|
17768
19189
|
const params = placeholdersToParams(placeholders);
|
|
17769
19190
|
i18nAttrArgs.push(literal(attr.name), this.i18nTranslate(message, params));
|
|
@@ -17983,7 +19404,7 @@ class TemplateDefinitionBuilder {
|
|
|
17983
19404
|
}
|
|
17984
19405
|
this.allocateBindingSlots(value);
|
|
17985
19406
|
if (inputType === 0 /* BindingType.Property */) {
|
|
17986
|
-
if (value instanceof Interpolation) {
|
|
19407
|
+
if (value instanceof Interpolation$1) {
|
|
17987
19408
|
// prop="{{value}}" and friends
|
|
17988
19409
|
this.interpolatedUpdateInstruction(getPropertyInterpolationExpression(value), elementIndex, attrName, input, value, params);
|
|
17989
19410
|
}
|
|
@@ -17997,12 +19418,12 @@ class TemplateDefinitionBuilder {
|
|
|
17997
19418
|
}
|
|
17998
19419
|
}
|
|
17999
19420
|
else if (inputType === 1 /* BindingType.Attribute */) {
|
|
18000
|
-
if (value instanceof Interpolation && getInterpolationArgsLength(value) > 1) {
|
|
19421
|
+
if (value instanceof Interpolation$1 && getInterpolationArgsLength(value) > 1) {
|
|
18001
19422
|
// attr.name="text{{value}}" and friends
|
|
18002
19423
|
this.interpolatedUpdateInstruction(getAttributeInterpolationExpression(value), elementIndex, attrName, input, value, params);
|
|
18003
19424
|
}
|
|
18004
19425
|
else {
|
|
18005
|
-
const boundValue = value instanceof Interpolation ? value.expressions[0] : value;
|
|
19426
|
+
const boundValue = value instanceof Interpolation$1 ? value.expressions[0] : value;
|
|
18006
19427
|
// [attr.name]="value" or attr.name="{{value}}"
|
|
18007
19428
|
// Collect the attribute bindings so that they can be chained at the end.
|
|
18008
19429
|
attributeBindings.push({
|
|
@@ -18072,7 +19493,7 @@ class TemplateDefinitionBuilder {
|
|
|
18072
19493
|
parameters.push(importExpr(Identifiers.templateRefExtractor));
|
|
18073
19494
|
}
|
|
18074
19495
|
// Create the template function
|
|
18075
|
-
const templateVisitor = new TemplateDefinitionBuilder(this.constantPool, this._bindingScope, this.level + 1, contextName, this.i18n, templateIndex, templateName, this._namespace, this.fileBasedI18nSuffix, this.i18nUseExternalIds, this._constants);
|
|
19496
|
+
const templateVisitor = new TemplateDefinitionBuilder(this.constantPool, this._bindingScope, this.level + 1, contextName, this.i18n, templateIndex, templateName, this._namespace, this.fileBasedI18nSuffix, this.i18nUseExternalIds, this.deferBlocks, this._constants);
|
|
18076
19497
|
// Nested templates must not be visited until after their parent templates have completed
|
|
18077
19498
|
// processing, so they are queued here until after the initial pass. Otherwise, we wouldn't
|
|
18078
19499
|
// be able to support bindings in nested templates to local refs that occur after the
|
|
@@ -18115,7 +19536,7 @@ class TemplateDefinitionBuilder {
|
|
|
18115
19536
|
if (this.i18n) {
|
|
18116
19537
|
const value = text.value.visit(this._valueConverter);
|
|
18117
19538
|
this.allocateBindingSlots(value);
|
|
18118
|
-
if (value instanceof Interpolation) {
|
|
19539
|
+
if (value instanceof Interpolation$1) {
|
|
18119
19540
|
this.i18n.appendBoundText(text.i18n);
|
|
18120
19541
|
this.i18nAppendBindings(value.expressions);
|
|
18121
19542
|
}
|
|
@@ -18125,7 +19546,7 @@ class TemplateDefinitionBuilder {
|
|
|
18125
19546
|
this.creationInstruction(text.sourceSpan, Identifiers.text, [literal(nodeIndex)]);
|
|
18126
19547
|
const value = text.value.visit(this._valueConverter);
|
|
18127
19548
|
this.allocateBindingSlots(value);
|
|
18128
|
-
if (value instanceof Interpolation) {
|
|
19549
|
+
if (value instanceof Interpolation$1) {
|
|
18129
19550
|
this.updateInstructionWithAdvance(nodeIndex, text.sourceSpan, getTextInterpolationExpression(value), () => this.getUpdateInstructionArguments(value));
|
|
18130
19551
|
}
|
|
18131
19552
|
else {
|
|
@@ -18182,6 +19603,47 @@ class TemplateDefinitionBuilder {
|
|
|
18182
19603
|
}
|
|
18183
19604
|
return null;
|
|
18184
19605
|
}
|
|
19606
|
+
visitDeferredBlock(deferred) {
|
|
19607
|
+
const templateIndex = this.allocateDataSlot();
|
|
19608
|
+
const deferredDeps = this.deferBlocks.get(deferred);
|
|
19609
|
+
const contextName = `${this.contextName}_Defer_${templateIndex}`;
|
|
19610
|
+
const depsFnName = `${contextName}_DepsFn`;
|
|
19611
|
+
const parameters = [
|
|
19612
|
+
literal(templateIndex),
|
|
19613
|
+
deferredDeps ? variable(depsFnName) : TYPED_NULL_EXPR,
|
|
19614
|
+
];
|
|
19615
|
+
if (deferredDeps) {
|
|
19616
|
+
// This defer block has deps for which we need to generate dynamic imports.
|
|
19617
|
+
const dependencyExp = [];
|
|
19618
|
+
for (const deferredDep of deferredDeps) {
|
|
19619
|
+
if (deferredDep.isDeferrable) {
|
|
19620
|
+
// Callback function, e.g. `function(m) { return m.MyCmp; }`.
|
|
19621
|
+
const innerFn = fn([new FnParam('m', DYNAMIC_TYPE)], [new ReturnStatement(variable('m').prop(deferredDep.symbolName))]);
|
|
19622
|
+
const fileName = deferredDep.importPath;
|
|
19623
|
+
// Dynamic import, e.g. `import('./a').then(...)`.
|
|
19624
|
+
const importExpr = (new DynamicImportExpr(fileName)).prop('then').callFn([innerFn]);
|
|
19625
|
+
dependencyExp.push(importExpr);
|
|
19626
|
+
}
|
|
19627
|
+
else {
|
|
19628
|
+
// Non-deferrable symbol, just use a reference to the type.
|
|
19629
|
+
dependencyExp.push(deferredDep.type);
|
|
19630
|
+
}
|
|
19631
|
+
}
|
|
19632
|
+
const depsFnBody = [];
|
|
19633
|
+
depsFnBody.push(new ReturnStatement(literalArr(dependencyExp)));
|
|
19634
|
+
const depsFnExpr = fn([] /* args */, depsFnBody, INFERRED_TYPE, null, depsFnName);
|
|
19635
|
+
this.constantPool.statements.push(depsFnExpr.toDeclStmt(depsFnName));
|
|
19636
|
+
}
|
|
19637
|
+
// e.g. `defer(1, MyComp_Defer_1_DepsFn, ...)`
|
|
19638
|
+
this.creationInstruction(deferred.sourceSpan, Identifiers.defer, () => {
|
|
19639
|
+
return trimTrailingNulls(parameters);
|
|
19640
|
+
});
|
|
19641
|
+
}
|
|
19642
|
+
// TODO: implement nested deferred block instructions.
|
|
19643
|
+
visitDeferredTrigger(trigger) { }
|
|
19644
|
+
visitDeferredBlockPlaceholder(block) { }
|
|
19645
|
+
visitDeferredBlockError(block) { }
|
|
19646
|
+
visitDeferredBlockLoading(block) { }
|
|
18185
19647
|
allocateDataSlot() {
|
|
18186
19648
|
return this._dataIndex++;
|
|
18187
19649
|
}
|
|
@@ -18213,7 +19675,7 @@ class TemplateDefinitionBuilder {
|
|
|
18213
19675
|
continue;
|
|
18214
19676
|
}
|
|
18215
19677
|
this.allocateBindingSlots(value);
|
|
18216
|
-
if (value instanceof Interpolation) {
|
|
19678
|
+
if (value instanceof Interpolation$1) {
|
|
18217
19679
|
// Params typically contain attribute namespace and value sanitizer, which is applicable
|
|
18218
19680
|
// for regular HTML elements, but not applicable for <ng-template> (since props act as
|
|
18219
19681
|
// inputs to directives), so keep params array empty.
|
|
@@ -18245,7 +19707,7 @@ class TemplateDefinitionBuilder {
|
|
|
18245
19707
|
if (instruction) {
|
|
18246
19708
|
for (const call of instruction.calls) {
|
|
18247
19709
|
allocateBindingSlots += call.allocateBindingSlots;
|
|
18248
|
-
this.updateInstructionWithAdvance(elementIndex, call.sourceSpan, instruction.reference, () => call.params(value => (call.supportsInterpolation && value instanceof Interpolation) ?
|
|
19710
|
+
this.updateInstructionWithAdvance(elementIndex, call.sourceSpan, instruction.reference, () => call.params(value => (call.supportsInterpolation && value instanceof Interpolation$1) ?
|
|
18249
19711
|
this.getUpdateInstructionArguments(value) :
|
|
18250
19712
|
this.convertPropertyBinding(value)));
|
|
18251
19713
|
}
|
|
@@ -18278,7 +19740,7 @@ class TemplateDefinitionBuilder {
|
|
|
18278
19740
|
return originalSlots;
|
|
18279
19741
|
}
|
|
18280
19742
|
allocateBindingSlots(value) {
|
|
18281
|
-
this._bindingSlots += value instanceof Interpolation ? value.expressions.length : 1;
|
|
19743
|
+
this._bindingSlots += value instanceof Interpolation$1 ? value.expressions.length : 1;
|
|
18282
19744
|
}
|
|
18283
19745
|
/**
|
|
18284
19746
|
* Gets an expression that refers to the implicit receiver. The implicit
|
|
@@ -18918,7 +20380,12 @@ function parseTemplate(template, templateUrl, options = {}) {
|
|
|
18918
20380
|
const { interpolationConfig, preserveWhitespaces, enableI18nLegacyMessageIdFormat } = options;
|
|
18919
20381
|
const bindingParser = makeBindingParser(interpolationConfig);
|
|
18920
20382
|
const htmlParser = new HtmlParser();
|
|
18921
|
-
const parseResult = htmlParser.parse(template, templateUrl, {
|
|
20383
|
+
const parseResult = htmlParser.parse(template, templateUrl, {
|
|
20384
|
+
leadingTriviaChars: LEADING_TRIVIA_CHARS,
|
|
20385
|
+
...options,
|
|
20386
|
+
tokenizeExpansionForms: true,
|
|
20387
|
+
tokenizeBlocks: options.enabledBlockTypes != null && options.enabledBlockTypes.size > 0,
|
|
20388
|
+
});
|
|
18922
20389
|
if (!options.alwaysAttemptHtmlToR3AstConversion && parseResult.errors &&
|
|
18923
20390
|
parseResult.errors.length > 0) {
|
|
18924
20391
|
const parsedTemplate = {
|
|
@@ -18969,7 +20436,10 @@ function parseTemplate(template, templateUrl, options = {}) {
|
|
|
18969
20436
|
rootNodes = visitAll(new I18nMetaVisitor(interpolationConfig, /* keepI18nAttrs */ false), rootNodes);
|
|
18970
20437
|
}
|
|
18971
20438
|
}
|
|
18972
|
-
const { nodes, errors, styleUrls, styles, ngContentSelectors, commentNodes } = htmlAstToRender3Ast(rootNodes, bindingParser, {
|
|
20439
|
+
const { nodes, errors, styleUrls, styles, ngContentSelectors, commentNodes } = htmlAstToRender3Ast(rootNodes, bindingParser, {
|
|
20440
|
+
collectCommentNodes: !!options.collectCommentNodes,
|
|
20441
|
+
enabledBlockTypes: options.enabledBlockTypes || new Set(),
|
|
20442
|
+
});
|
|
18973
20443
|
errors.push(...parseResult.errors, ...i18nMetaResult.errors);
|
|
18974
20444
|
const parsedTemplate = {
|
|
18975
20445
|
interpolationConfig,
|
|
@@ -19223,7 +20693,7 @@ function compileComponentFromMetadata(meta, constantPool, bindingParser) {
|
|
|
19223
20693
|
// This is the main path currently used in compilation, which compiles the template with the
|
|
19224
20694
|
// legacy `TemplateDefinitionBuilder`.
|
|
19225
20695
|
const template = meta.template;
|
|
19226
|
-
const templateBuilder = new TemplateDefinitionBuilder(constantPool, BindingScope.createRootScope(), 0, templateTypeName, null, null, templateName, Identifiers.namespaceHTML, meta.relativeContextFilePath, meta.i18nUseExternalIds);
|
|
20696
|
+
const templateBuilder = new TemplateDefinitionBuilder(constantPool, BindingScope.createRootScope(), 0, templateTypeName, null, null, templateName, Identifiers.namespaceHTML, meta.relativeContextFilePath, meta.i18nUseExternalIds, meta.deferBlocks);
|
|
19227
20697
|
const templateFunctionExpression = templateBuilder.buildTemplateFunction(template.nodes, []);
|
|
19228
20698
|
// We need to provide this so that dynamically generated components know what
|
|
19229
20699
|
// projected content blocks to pass through to the component when it is
|
|
@@ -19472,6 +20942,9 @@ function createViewQueriesFunction(viewQueries, constantPool, name) {
|
|
|
19472
20942
|
}
|
|
19473
20943
|
// Return a host binding function or null if one is not necessary.
|
|
19474
20944
|
function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindingParser, constantPool, selector, name, definitionMap) {
|
|
20945
|
+
const bindings = bindingParser.createBoundHostProperties(hostBindingsMetadata.properties, typeSourceSpan);
|
|
20946
|
+
// Calculate host event bindings
|
|
20947
|
+
const eventBindings = bindingParser.createDirectiveHostEventAsts(hostBindingsMetadata.listeners, typeSourceSpan);
|
|
19475
20948
|
const bindingContext = variable(CONTEXT_NAME);
|
|
19476
20949
|
const styleBuilder = new StylingBuilder(bindingContext);
|
|
19477
20950
|
const { styleAttr, classAttr } = hostBindingsMetadata.specialAttributes;
|
|
@@ -19485,13 +20958,10 @@ function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindin
|
|
|
19485
20958
|
const updateInstructions = [];
|
|
19486
20959
|
const updateVariables = [];
|
|
19487
20960
|
const hostBindingSourceSpan = typeSourceSpan;
|
|
19488
|
-
// Calculate host event bindings
|
|
19489
|
-
const eventBindings = bindingParser.createDirectiveHostEventAsts(hostBindingsMetadata.listeners, hostBindingSourceSpan);
|
|
19490
20961
|
if (eventBindings && eventBindings.length) {
|
|
19491
20962
|
createInstructions.push(...createHostListeners(eventBindings, name));
|
|
19492
20963
|
}
|
|
19493
20964
|
// Calculate the host property bindings
|
|
19494
|
-
const bindings = bindingParser.createBoundHostProperties(hostBindingsMetadata.properties, hostBindingSourceSpan);
|
|
19495
20965
|
const allOtherBindings = [];
|
|
19496
20966
|
// We need to calculate the total amount of binding slots required by
|
|
19497
20967
|
// all the instructions together before any value conversions happen.
|
|
@@ -19834,6 +21304,7 @@ function createHostDirectivesMappingArray(mapping) {
|
|
|
19834
21304
|
class ResourceLoader {
|
|
19835
21305
|
}
|
|
19836
21306
|
|
|
21307
|
+
let enabledBlockTypes;
|
|
19837
21308
|
class CompilerFacadeImpl {
|
|
19838
21309
|
constructor(jitEvaluator = new JitEvaluator()) {
|
|
19839
21310
|
this.jitEvaluator = jitEvaluator;
|
|
@@ -19954,6 +21425,10 @@ class CompilerFacadeImpl {
|
|
|
19954
21425
|
template,
|
|
19955
21426
|
declarations: facade.declarations.map(convertDeclarationFacadeToMetadata),
|
|
19956
21427
|
declarationListEmitMode: 0 /* DeclarationListEmitMode.Direct */,
|
|
21428
|
+
// TODO: leaving empty in JIT mode for now,
|
|
21429
|
+
// to be implemented as one of the next steps.
|
|
21430
|
+
deferBlocks: new Map(),
|
|
21431
|
+
deferrableDeclToImportDecl: new Map(),
|
|
19957
21432
|
styles: [...facade.styles, ...template.styles],
|
|
19958
21433
|
encapsulation: facade.encapsulation,
|
|
19959
21434
|
interpolation,
|
|
@@ -20184,6 +21659,10 @@ function convertDeclareComponentFacadeToMetadata(decl, typeSourceSpan, sourceMap
|
|
|
20184
21659
|
viewProviders: decl.viewProviders !== undefined ? new WrappedNodeExpr(decl.viewProviders) :
|
|
20185
21660
|
null,
|
|
20186
21661
|
animations: decl.animations !== undefined ? new WrappedNodeExpr(decl.animations) : null,
|
|
21662
|
+
// TODO: leaving empty in JIT mode for now,
|
|
21663
|
+
// to be implemented as one of the next steps.
|
|
21664
|
+
deferBlocks: new Map(),
|
|
21665
|
+
deferrableDeclToImportDecl: new Map(),
|
|
20187
21666
|
changeDetection: decl.changeDetection ?? exports.ChangeDetectionStrategy.Default,
|
|
20188
21667
|
encapsulation: decl.encapsulation ?? exports.ViewEncapsulation.Emulated,
|
|
20189
21668
|
interpolation,
|
|
@@ -20231,7 +21710,7 @@ function convertPipeDeclarationToMetadata(pipe) {
|
|
|
20231
21710
|
function parseJitTemplate(template, typeName, sourceMapUrl, preserveWhitespaces, interpolation) {
|
|
20232
21711
|
const interpolationConfig = interpolation ? InterpolationConfig.fromArray(interpolation) : DEFAULT_INTERPOLATION_CONFIG;
|
|
20233
21712
|
// Parse the template and check for errors.
|
|
20234
|
-
const parsed = parseTemplate(template, sourceMapUrl, { preserveWhitespaces, interpolationConfig });
|
|
21713
|
+
const parsed = parseTemplate(template, sourceMapUrl, { preserveWhitespaces, interpolationConfig, enabledBlockTypes });
|
|
20235
21714
|
if (parsed.errors !== null) {
|
|
20236
21715
|
const errors = parsed.errors.map(err => err.toString()).join(', ');
|
|
20237
21716
|
throw new Error(`Errors during JIT compilation of template for ${typeName}: ${errors}`);
|
|
@@ -20420,7 +21899,7 @@ function publishFacade(global) {
|
|
|
20420
21899
|
* @description
|
|
20421
21900
|
* Entry point for all public APIs of the compiler package.
|
|
20422
21901
|
*/
|
|
20423
|
-
const VERSION = new Version('16.
|
|
21902
|
+
const VERSION = new Version('16.2.3');
|
|
20424
21903
|
|
|
20425
21904
|
class CompilerConfig {
|
|
20426
21905
|
constructor({ defaultEncapsulation = exports.ViewEncapsulation.Emulated, useJit = true, missingTranslation = null, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
@@ -20641,6 +22120,13 @@ class _Visitor {
|
|
|
20641
22120
|
visitAttribute(attribute, context) {
|
|
20642
22121
|
throw new Error('unreachable code');
|
|
20643
22122
|
}
|
|
22123
|
+
visitBlockGroup(group, context) {
|
|
22124
|
+
visitAll(this, group.blocks, context);
|
|
22125
|
+
}
|
|
22126
|
+
visitBlock(block, context) {
|
|
22127
|
+
visitAll(this, block.children, context);
|
|
22128
|
+
}
|
|
22129
|
+
visitBlockParameter(parameter, context) { }
|
|
20644
22130
|
_init(mode, interpolationConfig) {
|
|
20645
22131
|
this._mode = mode;
|
|
20646
22132
|
this._inI18nBlock = false;
|
|
@@ -20853,8 +22339,9 @@ class XmlParser extends Parser {
|
|
|
20853
22339
|
constructor() {
|
|
20854
22340
|
super(getXmlTagDefinition);
|
|
20855
22341
|
}
|
|
20856
|
-
parse(source, url, options) {
|
|
20857
|
-
|
|
22342
|
+
parse(source, url, options = {}) {
|
|
22343
|
+
// Blocks aren't supported in an XML context.
|
|
22344
|
+
return super.parse(source, url, { ...options, tokenizeBlocks: false });
|
|
20858
22345
|
}
|
|
20859
22346
|
}
|
|
20860
22347
|
|
|
@@ -21038,6 +22525,9 @@ class XliffParser {
|
|
|
21038
22525
|
visitComment(comment, context) { }
|
|
21039
22526
|
visitExpansion(expansion, context) { }
|
|
21040
22527
|
visitExpansionCase(expansionCase, context) { }
|
|
22528
|
+
visitBlockGroup(group, context) { }
|
|
22529
|
+
visitBlock(block, context) { }
|
|
22530
|
+
visitBlockParameter(parameter, context) { }
|
|
21041
22531
|
_addError(node, message) {
|
|
21042
22532
|
this._errors.push(new I18nError(node.sourceSpan, message));
|
|
21043
22533
|
}
|
|
@@ -21088,6 +22578,9 @@ class XmlToI18n$2 {
|
|
|
21088
22578
|
}
|
|
21089
22579
|
visitComment(comment, context) { }
|
|
21090
22580
|
visitAttribute(attribute, context) { }
|
|
22581
|
+
visitBlockGroup(group, context) { }
|
|
22582
|
+
visitBlock(block, context) { }
|
|
22583
|
+
visitBlockParameter(parameter, context) { }
|
|
21091
22584
|
_addError(node, message) {
|
|
21092
22585
|
this._errors.push(new I18nError(node.sourceSpan, message));
|
|
21093
22586
|
}
|
|
@@ -21311,6 +22804,9 @@ class Xliff2Parser {
|
|
|
21311
22804
|
visitComment(comment, context) { }
|
|
21312
22805
|
visitExpansion(expansion, context) { }
|
|
21313
22806
|
visitExpansionCase(expansionCase, context) { }
|
|
22807
|
+
visitBlockGroup(group, context) { }
|
|
22808
|
+
visitBlock(block, context) { }
|
|
22809
|
+
visitBlockParameter(parameter, context) { }
|
|
21314
22810
|
_addError(node, message) {
|
|
21315
22811
|
this._errors.push(new I18nError(node.sourceSpan, message));
|
|
21316
22812
|
}
|
|
@@ -21378,6 +22874,9 @@ class XmlToI18n$1 {
|
|
|
21378
22874
|
}
|
|
21379
22875
|
visitComment(comment, context) { }
|
|
21380
22876
|
visitAttribute(attribute, context) { }
|
|
22877
|
+
visitBlockGroup(group, context) { }
|
|
22878
|
+
visitBlock(block, context) { }
|
|
22879
|
+
visitBlockParameter(parameter, context) { }
|
|
21381
22880
|
_addError(node, message) {
|
|
21382
22881
|
this._errors.push(new I18nError(node.sourceSpan, message));
|
|
21383
22882
|
}
|
|
@@ -21512,6 +23011,9 @@ class XtbParser {
|
|
|
21512
23011
|
visitComment(comment, context) { }
|
|
21513
23012
|
visitExpansion(expansion, context) { }
|
|
21514
23013
|
visitExpansionCase(expansionCase, context) { }
|
|
23014
|
+
visitBlockGroup(group, context) { }
|
|
23015
|
+
visitBlock(block, context) { }
|
|
23016
|
+
visitBlockParameter(block, context) { }
|
|
21515
23017
|
_addError(node, message) {
|
|
21516
23018
|
this._errors.push(new I18nError(node.sourceSpan, message));
|
|
21517
23019
|
}
|
|
@@ -21560,6 +23062,9 @@ class XmlToI18n {
|
|
|
21560
23062
|
}
|
|
21561
23063
|
visitComment(comment, context) { }
|
|
21562
23064
|
visitAttribute(attribute, context) { }
|
|
23065
|
+
visitBlockGroup(group, context) { }
|
|
23066
|
+
visitBlock(block, context) { }
|
|
23067
|
+
visitBlockParameter(block, context) { }
|
|
21563
23068
|
_addError(node, message) {
|
|
21564
23069
|
this._errors.push(new I18nError(node.sourceSpan, message));
|
|
21565
23070
|
}
|
|
@@ -21862,11 +23367,11 @@ class R3TargetBinder {
|
|
|
21862
23367
|
// - bindings: Map of inputs, outputs, and attributes to the directive/element that claims
|
|
21863
23368
|
// them. TODO(alxhub): handle multiple directives claiming an input/output/etc.
|
|
21864
23369
|
// - references: Map of #references to their targets.
|
|
21865
|
-
const { directives, bindings, references } = DirectiveBinder.apply(target.template, this.directiveMatcher);
|
|
23370
|
+
const { directives, eagerDirectives, bindings, references } = DirectiveBinder.apply(target.template, this.directiveMatcher);
|
|
21866
23371
|
// Finally, run the TemplateBinder to bind references, variables, and other entities within the
|
|
21867
23372
|
// template. This extracts all the metadata that doesn't depend on directive matching.
|
|
21868
|
-
const { expressions, symbols, nestingLevel, usedPipes } = TemplateBinder.applyWithScope(target.template, scope);
|
|
21869
|
-
return new R3BoundTarget(target, directives, bindings, references, expressions, symbols, nestingLevel, templateEntities, usedPipes);
|
|
23373
|
+
const { expressions, symbols, nestingLevel, usedPipes, eagerPipes, deferBlocks } = TemplateBinder.applyWithScope(target.template, scope);
|
|
23374
|
+
return new R3BoundTarget(target, directives, eagerDirectives, bindings, references, expressions, symbols, nestingLevel, templateEntities, usedPipes, eagerPipes, deferBlocks);
|
|
21870
23375
|
}
|
|
21871
23376
|
}
|
|
21872
23377
|
/**
|
|
@@ -21939,6 +23444,21 @@ class Scope {
|
|
|
21939
23444
|
// Declare the variable if it's not already.
|
|
21940
23445
|
this.maybeDeclare(reference);
|
|
21941
23446
|
}
|
|
23447
|
+
visitDeferredBlock(deferred) {
|
|
23448
|
+
deferred.children.forEach(node => node.visit(this));
|
|
23449
|
+
deferred.placeholder?.visit(this);
|
|
23450
|
+
deferred.loading?.visit(this);
|
|
23451
|
+
deferred.error?.visit(this);
|
|
23452
|
+
}
|
|
23453
|
+
visitDeferredBlockPlaceholder(block) {
|
|
23454
|
+
block.children.forEach(node => node.visit(this));
|
|
23455
|
+
}
|
|
23456
|
+
visitDeferredBlockError(block) {
|
|
23457
|
+
block.children.forEach(node => node.visit(this));
|
|
23458
|
+
}
|
|
23459
|
+
visitDeferredBlockLoading(block) {
|
|
23460
|
+
block.children.forEach(node => node.visit(this));
|
|
23461
|
+
}
|
|
21942
23462
|
// Unused visitors.
|
|
21943
23463
|
visitContent(content) { }
|
|
21944
23464
|
visitBoundAttribute(attr) { }
|
|
@@ -21947,6 +23467,7 @@ class Scope {
|
|
|
21947
23467
|
visitText(text) { }
|
|
21948
23468
|
visitTextAttribute(attr) { }
|
|
21949
23469
|
visitIcu(icu) { }
|
|
23470
|
+
visitDeferredTrigger(trigger) { }
|
|
21950
23471
|
maybeDeclare(thing) {
|
|
21951
23472
|
// Declare something with a name, as long as that name isn't taken.
|
|
21952
23473
|
if (!this.namedEntities.has(thing.name)) {
|
|
@@ -21991,11 +23512,14 @@ class Scope {
|
|
|
21991
23512
|
* Usually used via the static `apply()` method.
|
|
21992
23513
|
*/
|
|
21993
23514
|
class DirectiveBinder {
|
|
21994
|
-
constructor(matcher, directives, bindings, references) {
|
|
23515
|
+
constructor(matcher, directives, eagerDirectives, bindings, references) {
|
|
21995
23516
|
this.matcher = matcher;
|
|
21996
23517
|
this.directives = directives;
|
|
23518
|
+
this.eagerDirectives = eagerDirectives;
|
|
21997
23519
|
this.bindings = bindings;
|
|
21998
23520
|
this.references = references;
|
|
23521
|
+
// Indicates whether we are visiting elements within a {#defer} block
|
|
23522
|
+
this.isInDeferBlock = false;
|
|
21999
23523
|
}
|
|
22000
23524
|
/**
|
|
22001
23525
|
* Process a template (list of `Node`s) and perform directive matching against each node.
|
|
@@ -22013,9 +23537,10 @@ class DirectiveBinder {
|
|
|
22013
23537
|
const directives = new Map();
|
|
22014
23538
|
const bindings = new Map();
|
|
22015
23539
|
const references = new Map();
|
|
22016
|
-
const
|
|
23540
|
+
const eagerDirectives = [];
|
|
23541
|
+
const matcher = new DirectiveBinder(selectorMatcher, directives, eagerDirectives, bindings, references);
|
|
22017
23542
|
matcher.ingest(template);
|
|
22018
|
-
return { directives, bindings, references };
|
|
23543
|
+
return { directives, eagerDirectives, bindings, references };
|
|
22019
23544
|
}
|
|
22020
23545
|
ingest(template) {
|
|
22021
23546
|
template.forEach(node => node.visit(this));
|
|
@@ -22035,6 +23560,9 @@ class DirectiveBinder {
|
|
|
22035
23560
|
this.matcher.match(cssSelector, (_selector, results) => directives.push(...results));
|
|
22036
23561
|
if (directives.length > 0) {
|
|
22037
23562
|
this.directives.set(node, directives);
|
|
23563
|
+
if (!this.isInDeferBlock) {
|
|
23564
|
+
this.eagerDirectives.push(...directives);
|
|
23565
|
+
}
|
|
22038
23566
|
}
|
|
22039
23567
|
// Resolve any references that are created on this node.
|
|
22040
23568
|
node.references.forEach(ref => {
|
|
@@ -22084,6 +23612,23 @@ class DirectiveBinder {
|
|
|
22084
23612
|
// Recurse into the node's children.
|
|
22085
23613
|
node.children.forEach(child => child.visit(this));
|
|
22086
23614
|
}
|
|
23615
|
+
visitDeferredBlock(deferred) {
|
|
23616
|
+
this.isInDeferBlock = true;
|
|
23617
|
+
deferred.children.forEach(child => child.visit(this));
|
|
23618
|
+
this.isInDeferBlock = false;
|
|
23619
|
+
deferred.placeholder?.visit(this);
|
|
23620
|
+
deferred.loading?.visit(this);
|
|
23621
|
+
deferred.error?.visit(this);
|
|
23622
|
+
}
|
|
23623
|
+
visitDeferredBlockPlaceholder(block) {
|
|
23624
|
+
block.children.forEach(child => child.visit(this));
|
|
23625
|
+
}
|
|
23626
|
+
visitDeferredBlockError(block) {
|
|
23627
|
+
block.children.forEach(child => child.visit(this));
|
|
23628
|
+
}
|
|
23629
|
+
visitDeferredBlockLoading(block) {
|
|
23630
|
+
block.children.forEach(child => child.visit(this));
|
|
23631
|
+
}
|
|
22087
23632
|
// Unused visitors.
|
|
22088
23633
|
visitContent(content) { }
|
|
22089
23634
|
visitVariable(variable) { }
|
|
@@ -22095,6 +23640,7 @@ class DirectiveBinder {
|
|
|
22095
23640
|
visitText(text) { }
|
|
22096
23641
|
visitBoundText(text) { }
|
|
22097
23642
|
visitIcu(icu) { }
|
|
23643
|
+
visitDeferredTrigger(trigger) { }
|
|
22098
23644
|
}
|
|
22099
23645
|
/**
|
|
22100
23646
|
* Processes a template and extract metadata about expressions and symbols within.
|
|
@@ -22106,15 +23652,19 @@ class DirectiveBinder {
|
|
|
22106
23652
|
* by overridden methods from that visitor.
|
|
22107
23653
|
*/
|
|
22108
23654
|
class TemplateBinder extends RecursiveAstVisitor {
|
|
22109
|
-
constructor(bindings, symbols, usedPipes, nestingLevel, scope, template, level) {
|
|
23655
|
+
constructor(bindings, symbols, usedPipes, eagerPipes, deferBlocks, nestingLevel, scope, template, level) {
|
|
22110
23656
|
super();
|
|
22111
23657
|
this.bindings = bindings;
|
|
22112
23658
|
this.symbols = symbols;
|
|
22113
23659
|
this.usedPipes = usedPipes;
|
|
23660
|
+
this.eagerPipes = eagerPipes;
|
|
23661
|
+
this.deferBlocks = deferBlocks;
|
|
22114
23662
|
this.nestingLevel = nestingLevel;
|
|
22115
23663
|
this.scope = scope;
|
|
22116
23664
|
this.template = template;
|
|
22117
23665
|
this.level = level;
|
|
23666
|
+
// Indicates whether we are visiting elements within a {#defer} block
|
|
23667
|
+
this.isInDeferBlock = false;
|
|
22118
23668
|
// Save a bit of processing time by constructing this closure in advance.
|
|
22119
23669
|
this.visitNode = (node) => node.visit(this);
|
|
22120
23670
|
}
|
|
@@ -22132,7 +23682,7 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
22132
23682
|
/**
|
|
22133
23683
|
* Process a template and extract metadata about expressions and symbols within.
|
|
22134
23684
|
*
|
|
22135
|
-
* @param
|
|
23685
|
+
* @param nodes the nodes of the template to process
|
|
22136
23686
|
* @param scope the `Scope` of the template being processed.
|
|
22137
23687
|
* @returns three maps which contain metadata about the template: `expressions` which interprets
|
|
22138
23688
|
* special `AST` nodes in expressions as pointing to references or variables declared within the
|
|
@@ -22141,15 +23691,18 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
22141
23691
|
* nesting level (how many levels deep within the template structure the `Template` is), starting
|
|
22142
23692
|
* at 1.
|
|
22143
23693
|
*/
|
|
22144
|
-
static applyWithScope(
|
|
23694
|
+
static applyWithScope(nodes, scope) {
|
|
22145
23695
|
const expressions = new Map();
|
|
22146
23696
|
const symbols = new Map();
|
|
22147
23697
|
const nestingLevel = new Map();
|
|
22148
23698
|
const usedPipes = new Set();
|
|
23699
|
+
const eagerPipes = new Set();
|
|
23700
|
+
const template = nodes instanceof Template ? nodes : null;
|
|
23701
|
+
const deferBlocks = new Set();
|
|
22149
23702
|
// The top-level template has nesting level 0.
|
|
22150
|
-
const binder = new TemplateBinder(expressions, symbols, usedPipes, nestingLevel, scope, template
|
|
22151
|
-
binder.ingest(
|
|
22152
|
-
return { expressions, symbols, nestingLevel, usedPipes };
|
|
23703
|
+
const binder = new TemplateBinder(expressions, symbols, usedPipes, eagerPipes, deferBlocks, nestingLevel, scope, template, 0);
|
|
23704
|
+
binder.ingest(nodes);
|
|
23705
|
+
return { expressions, symbols, nestingLevel, usedPipes, eagerPipes, deferBlocks };
|
|
22153
23706
|
}
|
|
22154
23707
|
ingest(template) {
|
|
22155
23708
|
if (template instanceof Template) {
|
|
@@ -22180,7 +23733,7 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
22180
23733
|
template.references.forEach(this.visitNode);
|
|
22181
23734
|
// Next, recurse into the template using its scope, and bumping the nesting level up by one.
|
|
22182
23735
|
const childScope = this.scope.getChildScope(template);
|
|
22183
|
-
const binder = new TemplateBinder(this.bindings, this.symbols, this.usedPipes, this.nestingLevel, childScope, template, this.level + 1);
|
|
23736
|
+
const binder = new TemplateBinder(this.bindings, this.symbols, this.usedPipes, this.eagerPipes, this.deferBlocks, this.nestingLevel, childScope, template, this.level + 1);
|
|
22184
23737
|
binder.ingest(template);
|
|
22185
23738
|
}
|
|
22186
23739
|
visitVariable(variable) {
|
|
@@ -22210,11 +23763,39 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
22210
23763
|
visitBoundEvent(event) {
|
|
22211
23764
|
event.handler.visit(this);
|
|
22212
23765
|
}
|
|
23766
|
+
visitDeferredBlock(deferred) {
|
|
23767
|
+
this.deferBlocks.add(deferred);
|
|
23768
|
+
this.isInDeferBlock = true;
|
|
23769
|
+
deferred.children.forEach(this.visitNode);
|
|
23770
|
+
this.isInDeferBlock = false;
|
|
23771
|
+
deferred.triggers.forEach(this.visitNode);
|
|
23772
|
+
deferred.prefetchTriggers.forEach(this.visitNode);
|
|
23773
|
+
deferred.placeholder && this.visitNode(deferred.placeholder);
|
|
23774
|
+
deferred.loading && this.visitNode(deferred.loading);
|
|
23775
|
+
deferred.error && this.visitNode(deferred.error);
|
|
23776
|
+
}
|
|
23777
|
+
visitDeferredTrigger(trigger) {
|
|
23778
|
+
if (trigger instanceof BoundDeferredTrigger) {
|
|
23779
|
+
trigger.value.visit(this);
|
|
23780
|
+
}
|
|
23781
|
+
}
|
|
23782
|
+
visitDeferredBlockPlaceholder(block) {
|
|
23783
|
+
block.children.forEach(this.visitNode);
|
|
23784
|
+
}
|
|
23785
|
+
visitDeferredBlockError(block) {
|
|
23786
|
+
block.children.forEach(this.visitNode);
|
|
23787
|
+
}
|
|
23788
|
+
visitDeferredBlockLoading(block) {
|
|
23789
|
+
block.children.forEach(this.visitNode);
|
|
23790
|
+
}
|
|
22213
23791
|
visitBoundText(text) {
|
|
22214
23792
|
text.value.visit(this);
|
|
22215
23793
|
}
|
|
22216
23794
|
visitPipe(ast, context) {
|
|
22217
23795
|
this.usedPipes.add(ast.name);
|
|
23796
|
+
if (!this.isInDeferBlock) {
|
|
23797
|
+
this.eagerPipes.add(ast.name);
|
|
23798
|
+
}
|
|
22218
23799
|
return super.visitPipe(ast, context);
|
|
22219
23800
|
}
|
|
22220
23801
|
// These five types of AST expressions can refer to expression roots, which could be variables
|
|
@@ -22251,9 +23832,10 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
22251
23832
|
* See `BoundTarget` for documentation on the individual methods.
|
|
22252
23833
|
*/
|
|
22253
23834
|
class R3BoundTarget {
|
|
22254
|
-
constructor(target, directives, bindings, references, exprTargets, symbols, nestingLevel, templateEntities, usedPipes) {
|
|
23835
|
+
constructor(target, directives, eagerDirectives, bindings, references, exprTargets, symbols, nestingLevel, templateEntities, usedPipes, eagerPipes, deferredBlocks) {
|
|
22255
23836
|
this.target = target;
|
|
22256
23837
|
this.directives = directives;
|
|
23838
|
+
this.eagerDirectives = eagerDirectives;
|
|
22257
23839
|
this.bindings = bindings;
|
|
22258
23840
|
this.references = references;
|
|
22259
23841
|
this.exprTargets = exprTargets;
|
|
@@ -22261,6 +23843,8 @@ class R3BoundTarget {
|
|
|
22261
23843
|
this.nestingLevel = nestingLevel;
|
|
22262
23844
|
this.templateEntities = templateEntities;
|
|
22263
23845
|
this.usedPipes = usedPipes;
|
|
23846
|
+
this.eagerPipes = eagerPipes;
|
|
23847
|
+
this.deferredBlocks = deferredBlocks;
|
|
22264
23848
|
}
|
|
22265
23849
|
getEntitiesInTemplateScope(template) {
|
|
22266
23850
|
return this.templateEntities.get(template) ?? new Set();
|
|
@@ -22288,9 +23872,19 @@ class R3BoundTarget {
|
|
|
22288
23872
|
this.directives.forEach(dirs => dirs.forEach(dir => set.add(dir)));
|
|
22289
23873
|
return Array.from(set.values());
|
|
22290
23874
|
}
|
|
23875
|
+
getEagerlyUsedDirectives() {
|
|
23876
|
+
const set = new Set(this.eagerDirectives);
|
|
23877
|
+
return Array.from(set.values());
|
|
23878
|
+
}
|
|
22291
23879
|
getUsedPipes() {
|
|
22292
23880
|
return Array.from(this.usedPipes);
|
|
22293
23881
|
}
|
|
23882
|
+
getEagerlyUsedPipes() {
|
|
23883
|
+
return Array.from(this.eagerPipes);
|
|
23884
|
+
}
|
|
23885
|
+
getDeferBlocks() {
|
|
23886
|
+
return Array.from(this.deferredBlocks);
|
|
23887
|
+
}
|
|
22294
23888
|
}
|
|
22295
23889
|
function extractTemplateEntities(rootScope) {
|
|
22296
23890
|
const entityMap = new Map();
|
|
@@ -22348,7 +23942,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
|
|
|
22348
23942
|
function compileDeclareClassMetadata(metadata) {
|
|
22349
23943
|
const definitionMap = new DefinitionMap();
|
|
22350
23944
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
22351
|
-
definitionMap.set('version', literal('16.
|
|
23945
|
+
definitionMap.set('version', literal('16.2.3'));
|
|
22352
23946
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
22353
23947
|
definitionMap.set('type', metadata.type);
|
|
22354
23948
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -22434,7 +24028,7 @@ function compileDependency(dep) {
|
|
|
22434
24028
|
*
|
|
22435
24029
|
* Do not include any prerelease in these versions as they are ignored.
|
|
22436
24030
|
*/
|
|
22437
|
-
const MINIMUM_PARTIAL_LINKER_VERSION$5 = '
|
|
24031
|
+
const MINIMUM_PARTIAL_LINKER_VERSION$5 = '16.1.0';
|
|
22438
24032
|
/**
|
|
22439
24033
|
* Compile a directive declaration defined by the `R3DirectiveMetadata`.
|
|
22440
24034
|
*/
|
|
@@ -22450,8 +24044,13 @@ function compileDeclareDirectiveFromMetadata(meta) {
|
|
|
22450
24044
|
*/
|
|
22451
24045
|
function createDirectiveDefinitionMap(meta) {
|
|
22452
24046
|
const definitionMap = new DefinitionMap();
|
|
22453
|
-
|
|
22454
|
-
|
|
24047
|
+
const hasTransformFunctions = Object.values(meta.inputs).some(input => input.transformFunction !== null);
|
|
24048
|
+
// Note: in order to allow consuming Angular libraries that have been compiled with 16.1+ in
|
|
24049
|
+
// Angular 16.0, we only force a minimum version of 16.1 if input transform feature as introduced
|
|
24050
|
+
// in 16.1 is actually used.
|
|
24051
|
+
const minVersion = hasTransformFunctions ? MINIMUM_PARTIAL_LINKER_VERSION$5 : '14.0.0';
|
|
24052
|
+
definitionMap.set('minVersion', literal(minVersion));
|
|
24053
|
+
definitionMap.set('version', literal('16.2.3'));
|
|
22455
24054
|
// e.g. `type: MyDirective`
|
|
22456
24055
|
definitionMap.set('type', meta.type.value);
|
|
22457
24056
|
if (meta.isStandalone) {
|
|
@@ -22676,7 +24275,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
22676
24275
|
function compileDeclareFactoryFunction(meta) {
|
|
22677
24276
|
const definitionMap = new DefinitionMap();
|
|
22678
24277
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
22679
|
-
definitionMap.set('version', literal('16.
|
|
24278
|
+
definitionMap.set('version', literal('16.2.3'));
|
|
22680
24279
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
22681
24280
|
definitionMap.set('type', meta.type.value);
|
|
22682
24281
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -22711,7 +24310,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
22711
24310
|
function createInjectableDefinitionMap(meta) {
|
|
22712
24311
|
const definitionMap = new DefinitionMap();
|
|
22713
24312
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
22714
|
-
definitionMap.set('version', literal('16.
|
|
24313
|
+
definitionMap.set('version', literal('16.2.3'));
|
|
22715
24314
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
22716
24315
|
definitionMap.set('type', meta.type.value);
|
|
22717
24316
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -22762,7 +24361,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
22762
24361
|
function createInjectorDefinitionMap(meta) {
|
|
22763
24362
|
const definitionMap = new DefinitionMap();
|
|
22764
24363
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
22765
|
-
definitionMap.set('version', literal('16.
|
|
24364
|
+
definitionMap.set('version', literal('16.2.3'));
|
|
22766
24365
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
22767
24366
|
definitionMap.set('type', meta.type.value);
|
|
22768
24367
|
definitionMap.set('providers', meta.providers);
|
|
@@ -22795,7 +24394,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
22795
24394
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
22796
24395
|
}
|
|
22797
24396
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
22798
|
-
definitionMap.set('version', literal('16.
|
|
24397
|
+
definitionMap.set('version', literal('16.2.3'));
|
|
22799
24398
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
22800
24399
|
definitionMap.set('type', meta.type.value);
|
|
22801
24400
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -22846,7 +24445,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
22846
24445
|
function createPipeDefinitionMap(meta) {
|
|
22847
24446
|
const definitionMap = new DefinitionMap();
|
|
22848
24447
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
22849
|
-
definitionMap.set('version', literal('16.
|
|
24448
|
+
definitionMap.set('version', literal('16.2.3'));
|
|
22850
24449
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
22851
24450
|
// e.g. `type: MyPipe`
|
|
22852
24451
|
definitionMap.set('type', meta.type.value);
|
|
@@ -22879,6 +24478,9 @@ exports.Attribute = Attribute;
|
|
|
22879
24478
|
exports.Binary = Binary;
|
|
22880
24479
|
exports.BinaryOperatorExpr = BinaryOperatorExpr;
|
|
22881
24480
|
exports.BindingPipe = BindingPipe;
|
|
24481
|
+
exports.Block = Block;
|
|
24482
|
+
exports.BlockGroup = BlockGroup;
|
|
24483
|
+
exports.BlockParameter = BlockParameter;
|
|
22882
24484
|
exports.BoundElementProperty = BoundElementProperty;
|
|
22883
24485
|
exports.BuiltinType = BuiltinType;
|
|
22884
24486
|
exports.CUSTOM_ELEMENTS_SCHEMA = CUSTOM_ELEMENTS_SCHEMA;
|
|
@@ -22896,11 +24498,12 @@ exports.DYNAMIC_TYPE = DYNAMIC_TYPE;
|
|
|
22896
24498
|
exports.DeclareFunctionStmt = DeclareFunctionStmt;
|
|
22897
24499
|
exports.DeclareVarStmt = DeclareVarStmt;
|
|
22898
24500
|
exports.DomElementSchemaRegistry = DomElementSchemaRegistry;
|
|
24501
|
+
exports.DynamicImportExpr = DynamicImportExpr;
|
|
22899
24502
|
exports.EOF = EOF;
|
|
22900
24503
|
exports.Element = Element;
|
|
22901
24504
|
exports.ElementSchemaRegistry = ElementSchemaRegistry;
|
|
22902
24505
|
exports.EmitterVisitorContext = EmitterVisitorContext;
|
|
22903
|
-
exports.EmptyExpr = EmptyExpr;
|
|
24506
|
+
exports.EmptyExpr = EmptyExpr$1;
|
|
22904
24507
|
exports.Expansion = Expansion;
|
|
22905
24508
|
exports.ExpansionCase = ExpansionCase;
|
|
22906
24509
|
exports.Expression = Expression;
|
|
@@ -22916,7 +24519,7 @@ exports.I18NHtmlParser = I18NHtmlParser;
|
|
|
22916
24519
|
exports.IfStmt = IfStmt;
|
|
22917
24520
|
exports.ImplicitReceiver = ImplicitReceiver;
|
|
22918
24521
|
exports.InstantiateExpr = InstantiateExpr;
|
|
22919
|
-
exports.Interpolation = Interpolation;
|
|
24522
|
+
exports.Interpolation = Interpolation$1;
|
|
22920
24523
|
exports.InterpolationConfig = InterpolationConfig;
|
|
22921
24524
|
exports.InvokeFunctionExpr = InvokeFunctionExpr;
|
|
22922
24525
|
exports.JSDocComment = JSDocComment;
|
|
@@ -22980,17 +24583,29 @@ exports.TemplateLiteralElement = TemplateLiteralElement;
|
|
|
22980
24583
|
exports.Text = Text;
|
|
22981
24584
|
exports.ThisReceiver = ThisReceiver;
|
|
22982
24585
|
exports.TmplAstBoundAttribute = BoundAttribute;
|
|
24586
|
+
exports.TmplAstBoundDeferredTrigger = BoundDeferredTrigger;
|
|
22983
24587
|
exports.TmplAstBoundEvent = BoundEvent;
|
|
22984
24588
|
exports.TmplAstBoundText = BoundText;
|
|
22985
24589
|
exports.TmplAstContent = Content;
|
|
24590
|
+
exports.TmplAstDeferredBlock = DeferredBlock;
|
|
24591
|
+
exports.TmplAstDeferredBlockError = DeferredBlockError;
|
|
24592
|
+
exports.TmplAstDeferredBlockLoading = DeferredBlockLoading;
|
|
24593
|
+
exports.TmplAstDeferredBlockPlaceholder = DeferredBlockPlaceholder;
|
|
24594
|
+
exports.TmplAstDeferredTrigger = DeferredTrigger;
|
|
22986
24595
|
exports.TmplAstElement = Element$1;
|
|
24596
|
+
exports.TmplAstHoverDeferredTrigger = HoverDeferredTrigger;
|
|
22987
24597
|
exports.TmplAstIcu = Icu$1;
|
|
24598
|
+
exports.TmplAstIdleDeferredTrigger = IdleDeferredTrigger;
|
|
24599
|
+
exports.TmplAstImmediateDeferredTrigger = ImmediateDeferredTrigger;
|
|
24600
|
+
exports.TmplAstInteractionDeferredTrigger = InteractionDeferredTrigger;
|
|
22988
24601
|
exports.TmplAstRecursiveVisitor = RecursiveVisitor$1;
|
|
22989
24602
|
exports.TmplAstReference = Reference;
|
|
22990
24603
|
exports.TmplAstTemplate = Template;
|
|
22991
24604
|
exports.TmplAstText = Text$3;
|
|
22992
24605
|
exports.TmplAstTextAttribute = TextAttribute;
|
|
24606
|
+
exports.TmplAstTimerDeferredTrigger = TimerDeferredTrigger;
|
|
22993
24607
|
exports.TmplAstVariable = Variable;
|
|
24608
|
+
exports.TmplAstViewportDeferredTrigger = ViewportDeferredTrigger;
|
|
22994
24609
|
exports.Token = Token;
|
|
22995
24610
|
exports.TransplantedType = TransplantedType;
|
|
22996
24611
|
exports.TreeError = TreeError;
|