@angular/compiler 17.0.0-next.2 → 17.0.0-next.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/src/compiler_util/expression_converter.mjs +22 -2
- package/esm2022/src/constant_pool.mjs +21 -2
- package/esm2022/src/output/output_ast.mjs +6 -3
- package/esm2022/src/render3/partial/class_metadata.mjs +1 -1
- package/esm2022/src/render3/partial/directive.mjs +1 -1
- package/esm2022/src/render3/partial/factory.mjs +1 -1
- package/esm2022/src/render3/partial/injectable.mjs +1 -1
- package/esm2022/src/render3/partial/injector.mjs +1 -1
- package/esm2022/src/render3/partial/ng_module.mjs +1 -1
- package/esm2022/src/render3/partial/pipe.mjs +1 -1
- package/esm2022/src/render3/r3_control_flow.mjs +7 -2
- package/esm2022/src/render3/r3_identifiers.mjs +2 -1
- package/esm2022/src/render3/view/template.mjs +132 -37
- package/esm2022/src/version.mjs +1 -1
- package/fesm2022/compiler.mjs +191 -48
- package/fesm2022/compiler.mjs.map +1 -1
- package/fesm2022/testing.mjs +1 -1
- package/index.d.ts +5 -2
- package/package.json +2 -2
- package/testing/index.d.ts +1 -1
package/esm2022/src/version.mjs
CHANGED
|
@@ -11,5 +11,5 @@
|
|
|
11
11
|
* Entry point for all public APIs of the compiler package.
|
|
12
12
|
*/
|
|
13
13
|
import { Version } from './util';
|
|
14
|
-
export const VERSION = new Version('17.0.0-next.
|
|
14
|
+
export const VERSION = new Version('17.0.0-next.3');
|
|
15
15
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy92ZXJzaW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVIOzs7O0dBSUc7QUFFSCxPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sUUFBUSxDQUFDO0FBRS9CLE1BQU0sQ0FBQyxNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbi8qKlxuICogQG1vZHVsZVxuICogQGRlc2NyaXB0aW9uXG4gKiBFbnRyeSBwb2ludCBmb3IgYWxsIHB1YmxpYyBBUElzIG9mIHRoZSBjb21waWxlciBwYWNrYWdlLlxuICovXG5cbmltcG9ydCB7VmVyc2lvbn0gZnJvbSAnLi91dGlsJztcblxuZXhwb3J0IGNvbnN0IFZFUlNJT04gPSBuZXcgVmVyc2lvbignMC4wLjAtUExBQ0VIT0xERVInKTtcbiJdfQ==
|
package/fesm2022/compiler.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v17.0.0-next.
|
|
2
|
+
* @license Angular v17.0.0-next.3
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -1677,8 +1677,8 @@ class FunctionExpr extends Expression {
|
|
|
1677
1677
|
this.name = name;
|
|
1678
1678
|
}
|
|
1679
1679
|
isEquivalent(e) {
|
|
1680
|
-
return e instanceof FunctionExpr
|
|
1681
|
-
areAllEquivalent(this.statements, e.statements);
|
|
1680
|
+
return (e instanceof FunctionExpr || e instanceof DeclareFunctionStmt) &&
|
|
1681
|
+
areAllEquivalent(this.params, e.params) && areAllEquivalent(this.statements, e.statements);
|
|
1682
1682
|
}
|
|
1683
1683
|
isConstant() {
|
|
1684
1684
|
return false;
|
|
@@ -1724,6 +1724,9 @@ class ArrowFunctionExpr extends Expression {
|
|
|
1724
1724
|
// TODO: Should we deep clone statements?
|
|
1725
1725
|
return new ArrowFunctionExpr(this.params.map(p => p.clone()), Array.isArray(this.body) ? this.body : this.body.clone(), this.type, this.sourceSpan);
|
|
1726
1726
|
}
|
|
1727
|
+
toDeclStmt(name, modifiers) {
|
|
1728
|
+
return new DeclareVarStmt(name, this, INFERRED_TYPE, modifiers, this.sourceSpan);
|
|
1729
|
+
}
|
|
1727
1730
|
}
|
|
1728
1731
|
class UnaryOperatorExpr extends Expression {
|
|
1729
1732
|
constructor(operator, expr, type, sourceSpan, parens = true) {
|
|
@@ -2515,13 +2518,32 @@ class ConstantPool {
|
|
|
2515
2518
|
}))));
|
|
2516
2519
|
}
|
|
2517
2520
|
}
|
|
2521
|
+
getSharedFunctionReference(fn, prefix) {
|
|
2522
|
+
const isArrow = fn instanceof ArrowFunctionExpr;
|
|
2523
|
+
for (const current of this.statements) {
|
|
2524
|
+
// Arrow functions are saved as variables so we check if the
|
|
2525
|
+
// value of the variable is the same as the arrow function.
|
|
2526
|
+
if (isArrow && current instanceof DeclareVarStmt && current.value?.isEquivalent(fn)) {
|
|
2527
|
+
return variable(current.name);
|
|
2528
|
+
}
|
|
2529
|
+
// Function declarations are saved as function statements
|
|
2530
|
+
// so we compare them directly to the passed-in function.
|
|
2531
|
+
if (!isArrow && current instanceof DeclareFunctionStmt && fn.isEquivalent(current)) {
|
|
2532
|
+
return variable(current.name);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
// Otherwise declare the function.
|
|
2536
|
+
const name = this.uniqueName(prefix);
|
|
2537
|
+
this.statements.push(fn.toDeclStmt(name, StmtModifier.Final));
|
|
2538
|
+
return variable(name);
|
|
2539
|
+
}
|
|
2518
2540
|
_getLiteralFactory(key, values, resultMap) {
|
|
2519
2541
|
let literalFactory = this.literalFactories.get(key);
|
|
2520
2542
|
const literalFactoryArguments = values.filter((e => !e.isConstant()));
|
|
2521
2543
|
if (!literalFactory) {
|
|
2522
2544
|
const resultExpressions = values.map((e, index) => e.isConstant() ? this.getConstLiteral(e, true) : variable(`a${index}`));
|
|
2523
2545
|
const parameters = resultExpressions.filter(isVariable).map(e => new FnParam(e.name, DYNAMIC_TYPE));
|
|
2524
|
-
const pureFunctionDeclaration =
|
|
2546
|
+
const pureFunctionDeclaration = arrowFn(parameters, resultMap(resultExpressions), INFERRED_TYPE);
|
|
2525
2547
|
const name = this.freshName();
|
|
2526
2548
|
this.statements.push(variable(name)
|
|
2527
2549
|
.set(pureFunctionDeclaration)
|
|
@@ -2678,6 +2700,7 @@ class Identifiers {
|
|
|
2678
2700
|
static { this.repeaterCreate = { name: 'ɵɵrepeaterCreate', moduleName: CORE }; }
|
|
2679
2701
|
static { this.repeaterTrackByIndex = { name: 'ɵɵrepeaterTrackByIndex', moduleName: CORE }; }
|
|
2680
2702
|
static { this.repeaterTrackByIdentity = { name: 'ɵɵrepeaterTrackByIdentity', moduleName: CORE }; }
|
|
2703
|
+
static { this.componentInstance = { name: 'ɵɵcomponentInstance', moduleName: CORE }; }
|
|
2681
2704
|
static { this.text = { name: 'ɵɵtext', moduleName: CORE }; }
|
|
2682
2705
|
static { this.enableBindings = { name: 'ɵɵenableBindings', moduleName: CORE }; }
|
|
2683
2706
|
static { this.disableBindings = { name: 'ɵɵdisableBindings', moduleName: CORE }; }
|
|
@@ -7051,6 +7074,26 @@ function convertPropertyBinding(localResolver, implicitReceiver, expressionWitho
|
|
|
7051
7074
|
}
|
|
7052
7075
|
return new ConvertPropertyBindingResult(stmts, outputExpr);
|
|
7053
7076
|
}
|
|
7077
|
+
/** Converts an AST to a pure function that may have access to the component scope. */
|
|
7078
|
+
function convertPureComponentScopeFunction(ast, localResolver, implicitReceiver, bindingId) {
|
|
7079
|
+
const converted = convertPropertyBindingBuiltins({
|
|
7080
|
+
createLiteralArrayConverter: () => args => literalArr(args),
|
|
7081
|
+
createLiteralMapConverter: keys => values => literalMap(keys.map((key, index) => {
|
|
7082
|
+
return ({
|
|
7083
|
+
key: key.key,
|
|
7084
|
+
value: values[index],
|
|
7085
|
+
quoted: key.quoted,
|
|
7086
|
+
});
|
|
7087
|
+
})),
|
|
7088
|
+
createPipeConverter: () => {
|
|
7089
|
+
throw new Error('Illegal State: Pipes are not allowed in this context');
|
|
7090
|
+
}
|
|
7091
|
+
}, ast);
|
|
7092
|
+
const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, false);
|
|
7093
|
+
const statements = [];
|
|
7094
|
+
flattenStatements(converted.visit(visitor, _Mode.Statement), statements);
|
|
7095
|
+
return statements;
|
|
7096
|
+
}
|
|
7054
7097
|
/**
|
|
7055
7098
|
* Given some expression, such as a binding or interpolation expression, and a context expression to
|
|
7056
7099
|
* look values up on, visit each facet of the given expression resolving values from the context
|
|
@@ -23083,7 +23126,12 @@ function validateSwitchBlock(ast) {
|
|
|
23083
23126
|
const [primaryBlock, ...secondaryBlocks] = ast.blocks;
|
|
23084
23127
|
const errors = [];
|
|
23085
23128
|
let hasDefault = false;
|
|
23086
|
-
|
|
23129
|
+
const hasPrimary = primaryBlock.children.length > 0 && primaryBlock.children.some(child => {
|
|
23130
|
+
// The main block might have empty text nodes if `preserveWhitespaces` is enabled.
|
|
23131
|
+
// Allow them since they might be used for code formatting.
|
|
23132
|
+
return !(child instanceof Text) || child.value.trim().length > 0;
|
|
23133
|
+
});
|
|
23134
|
+
if (hasPrimary) {
|
|
23087
23135
|
errors.push(new ParseError(primaryBlock.sourceSpan, 'Switch block can only contain "case" and "default" blocks'));
|
|
23088
23136
|
}
|
|
23089
23137
|
if (primaryBlock.parameters.length !== 1) {
|
|
@@ -24383,9 +24431,10 @@ function createComponentDefConsts() {
|
|
|
24383
24431
|
};
|
|
24384
24432
|
}
|
|
24385
24433
|
class TemplateData {
|
|
24386
|
-
constructor(name, index, visitor) {
|
|
24434
|
+
constructor(name, index, scope, visitor) {
|
|
24387
24435
|
this.name = name;
|
|
24388
24436
|
this.index = index;
|
|
24437
|
+
this.scope = scope;
|
|
24389
24438
|
this.visitor = visitor;
|
|
24390
24439
|
}
|
|
24391
24440
|
getConstCount() {
|
|
@@ -25059,7 +25108,7 @@ class TemplateDefinitionBuilder {
|
|
|
25059
25108
|
this._ngContentReservedSlots.push(...visitor._ngContentReservedSlots);
|
|
25060
25109
|
}
|
|
25061
25110
|
});
|
|
25062
|
-
return new TemplateData(name, index, visitor);
|
|
25111
|
+
return new TemplateData(name, index, visitor._bindingScope, visitor);
|
|
25063
25112
|
}
|
|
25064
25113
|
createEmbeddedTemplateFn(tagName, children, contextNameSuffix, sourceSpan, variables = [], attrsExprs, references, i18n) {
|
|
25065
25114
|
const data = this.prepareEmbeddedTemplateFn(children, contextNameSuffix, variables, i18n);
|
|
@@ -25345,8 +25394,8 @@ class TemplateDefinitionBuilder {
|
|
|
25345
25394
|
const dependencyExp = [];
|
|
25346
25395
|
for (const deferredDep of deferredDeps) {
|
|
25347
25396
|
if (deferredDep.isDeferrable) {
|
|
25348
|
-
// Callback function, e.g. `
|
|
25349
|
-
const innerFn =
|
|
25397
|
+
// Callback function, e.g. `m () => m.MyCmp;`.
|
|
25398
|
+
const innerFn = arrowFn([new FnParam('m', DYNAMIC_TYPE)], variable('m').prop(deferredDep.symbolName));
|
|
25350
25399
|
// Dynamic import, e.g. `import('./a').then(...)`.
|
|
25351
25400
|
const importExpr = (new DynamicImportExpr(deferredDep.importPath)).prop('then').callFn([innerFn]);
|
|
25352
25401
|
dependencyExp.push(importExpr);
|
|
@@ -25356,8 +25405,8 @@ class TemplateDefinitionBuilder {
|
|
|
25356
25405
|
dependencyExp.push(deferredDep.type);
|
|
25357
25406
|
}
|
|
25358
25407
|
}
|
|
25359
|
-
const depsFnExpr =
|
|
25360
|
-
this.constantPool.statements.push(depsFnExpr.toDeclStmt(name));
|
|
25408
|
+
const depsFnExpr = arrowFn([], literalArr(dependencyExp));
|
|
25409
|
+
this.constantPool.statements.push(depsFnExpr.toDeclStmt(name, StmtModifier.Final));
|
|
25361
25410
|
return variable(name);
|
|
25362
25411
|
}
|
|
25363
25412
|
createDeferTriggerInstructions(deferredIndex, triggers, prefetch) {
|
|
@@ -25406,14 +25455,18 @@ class TemplateDefinitionBuilder {
|
|
|
25406
25455
|
// Allocate one slot for the repeater metadata. The slots for the primary and empty block
|
|
25407
25456
|
// are implicitly inferred by the runtime to index + 1 and index + 2.
|
|
25408
25457
|
const blockIndex = this.allocateDataSlot();
|
|
25409
|
-
const
|
|
25410
|
-
|
|
25458
|
+
const primaryData = this.prepareEmbeddedTemplateFn(block.children, '_For', [
|
|
25459
|
+
new Variable(block.itemName, '$implicit', block.sourceSpan, block.sourceSpan),
|
|
25460
|
+
new Variable(getLoopLocalName(block, '$index'), '$index', block.sourceSpan, block.sourceSpan),
|
|
25461
|
+
new Variable(getLoopLocalName(block, '$count'), '$count', block.sourceSpan, block.sourceSpan),
|
|
25462
|
+
]);
|
|
25411
25463
|
const emptyData = block.empty === null ?
|
|
25412
25464
|
null :
|
|
25413
25465
|
this.prepareEmbeddedTemplateFn(block.empty.children, '_ForEmpty');
|
|
25414
|
-
const
|
|
25466
|
+
const { expression: trackByExpression, usesComponentInstance: trackByUsesComponentInstance } = this.createTrackByFunction(block);
|
|
25415
25467
|
const value = block.expression.visit(this._valueConverter);
|
|
25416
25468
|
this.allocateBindingSlots(value);
|
|
25469
|
+
this.registerComputedLoopVariables(block, primaryData.scope);
|
|
25417
25470
|
// `repeaterCreate(0, ...)`
|
|
25418
25471
|
this.creationInstruction(block.sourceSpan, Identifiers.repeaterCreate, () => {
|
|
25419
25472
|
const params = [
|
|
@@ -25421,53 +25474,100 @@ class TemplateDefinitionBuilder {
|
|
|
25421
25474
|
variable(primaryData.name),
|
|
25422
25475
|
literal(primaryData.getConstCount()),
|
|
25423
25476
|
literal(primaryData.getVarCount()),
|
|
25424
|
-
|
|
25477
|
+
trackByExpression,
|
|
25425
25478
|
];
|
|
25426
25479
|
if (emptyData !== null) {
|
|
25427
|
-
params.push(variable(emptyData.name), literal(emptyData.getConstCount()), literal(emptyData.getVarCount()));
|
|
25480
|
+
params.push(literal(trackByUsesComponentInstance), variable(emptyData.name), literal(emptyData.getConstCount()), literal(emptyData.getVarCount()));
|
|
25481
|
+
}
|
|
25482
|
+
else if (trackByUsesComponentInstance) {
|
|
25483
|
+
// If the tracking function doesn't use the component instance, we can omit the flag.
|
|
25484
|
+
params.push(literal(trackByUsesComponentInstance));
|
|
25428
25485
|
}
|
|
25429
25486
|
return params;
|
|
25430
25487
|
});
|
|
25431
25488
|
// `repeater(0, iterable)`
|
|
25432
25489
|
this.updateInstruction(block.sourceSpan, Identifiers.repeater, () => [literal(blockIndex), this.convertPropertyBinding(value)]);
|
|
25433
25490
|
}
|
|
25434
|
-
|
|
25491
|
+
registerComputedLoopVariables(block, bindingScope) {
|
|
25435
25492
|
const indexLocalName = getLoopLocalName(block, '$index');
|
|
25436
25493
|
const countLocalName = getLoopLocalName(block, '$count');
|
|
25437
|
-
|
|
25438
|
-
|
|
25439
|
-
|
|
25440
|
-
|
|
25441
|
-
|
|
25442
|
-
new Variable(block.itemName, '$implicit', block.sourceSpan, block.sourceSpan),
|
|
25443
|
-
new Variable(indexLocalName, '$index', block.sourceSpan, block.sourceSpan),
|
|
25444
|
-
new Variable(countLocalName, '$count', block.sourceSpan, block.sourceSpan),
|
|
25445
|
-
];
|
|
25494
|
+
const level = bindingScope.bindingLevel;
|
|
25495
|
+
bindingScope.set(level, getLoopLocalName(block, '$odd'), scope => scope.get(indexLocalName).modulo(literal(2)).notIdentical(literal(0)));
|
|
25496
|
+
bindingScope.set(level, getLoopLocalName(block, '$even'), scope => scope.get(indexLocalName).modulo(literal(2)).identical(literal(0)));
|
|
25497
|
+
bindingScope.set(level, getLoopLocalName(block, '$first'), scope => scope.get(indexLocalName).identical(literal(0)));
|
|
25498
|
+
bindingScope.set(level, getLoopLocalName(block, '$last'), scope => scope.get(indexLocalName).identical(scope.get(countLocalName).minus(literal(1))));
|
|
25446
25499
|
}
|
|
25447
|
-
|
|
25500
|
+
optimizeTrackByFunction(block) {
|
|
25448
25501
|
const ast = block.trackBy.ast;
|
|
25449
25502
|
// Top-level access of `$index` uses the built in `repeaterTrackByIndex`.
|
|
25450
25503
|
if (ast instanceof PropertyRead && ast.receiver instanceof ImplicitReceiver &&
|
|
25451
25504
|
ast.name === getLoopLocalName(block, '$index')) {
|
|
25452
|
-
return importExpr(Identifiers.repeaterTrackByIndex);
|
|
25505
|
+
return { expression: importExpr(Identifiers.repeaterTrackByIndex), usesComponentInstance: false };
|
|
25453
25506
|
}
|
|
25454
25507
|
// Top-level access of the item uses the built in `repeaterTrackByIdentity`.
|
|
25455
25508
|
if (ast instanceof PropertyRead && ast.receiver instanceof ImplicitReceiver &&
|
|
25456
25509
|
ast.name === block.itemName) {
|
|
25457
|
-
return importExpr(Identifiers.repeaterTrackByIdentity);
|
|
25510
|
+
return { expression: importExpr(Identifiers.repeaterTrackByIdentity), usesComponentInstance: false };
|
|
25511
|
+
}
|
|
25512
|
+
// Top-level calls in the form of `fn($index, item)` can be passed in directly.
|
|
25513
|
+
if (ast instanceof Call && ast.receiver instanceof PropertyRead &&
|
|
25514
|
+
ast.receiver.receiver instanceof ImplicitReceiver && ast.args.length === 2) {
|
|
25515
|
+
const firstIsIndex = ast.args[0] instanceof PropertyRead &&
|
|
25516
|
+
ast.args[0].receiver instanceof ImplicitReceiver &&
|
|
25517
|
+
ast.args[0].name === getLoopLocalName(block, '$index');
|
|
25518
|
+
const secondIsItem = ast.args[1] instanceof PropertyRead &&
|
|
25519
|
+
ast.args[1].receiver instanceof ImplicitReceiver && ast.args[1].name === block.itemName;
|
|
25520
|
+
if (firstIsIndex && secondIsItem) {
|
|
25521
|
+
// If we're in the top-level component, we can access directly through `ctx`,
|
|
25522
|
+
// otherwise we have to get a hold of the component through `componentInstance()`.
|
|
25523
|
+
const receiver = this.level === 0 ? variable(CONTEXT_NAME) :
|
|
25524
|
+
new ExternalExpr(Identifiers.componentInstance).callFn([]);
|
|
25525
|
+
return { expression: receiver.prop(ast.receiver.name), usesComponentInstance: false };
|
|
25526
|
+
}
|
|
25458
25527
|
}
|
|
25459
|
-
|
|
25460
|
-
|
|
25461
|
-
|
|
25462
|
-
|
|
25463
|
-
|
|
25464
|
-
|
|
25465
|
-
|
|
25466
|
-
|
|
25528
|
+
return null;
|
|
25529
|
+
}
|
|
25530
|
+
createTrackByFunction(block) {
|
|
25531
|
+
const optimizedFn = this.optimizeTrackByFunction(block);
|
|
25532
|
+
// If the tracking function can be optimized, we don't need any further processing.
|
|
25533
|
+
if (optimizedFn !== null) {
|
|
25534
|
+
return optimizedFn;
|
|
25535
|
+
}
|
|
25536
|
+
// Referencing these requires access to the context which the tracking function
|
|
25537
|
+
// might not have. `$index` is special because of backwards compatibility.
|
|
25538
|
+
const bannedGlobals = new Set([
|
|
25539
|
+
getLoopLocalName(block, '$count'), getLoopLocalName(block, '$first'),
|
|
25540
|
+
getLoopLocalName(block, '$last'), getLoopLocalName(block, '$even'),
|
|
25541
|
+
getLoopLocalName(block, '$odd')
|
|
25542
|
+
]);
|
|
25543
|
+
const scope = new TrackByBindingScope(this._bindingScope, {
|
|
25544
|
+
// Alias `$index` and the item name to `$index` and `$item` respectively.
|
|
25545
|
+
// This allows us to reuse pure functions that may have different item names,
|
|
25546
|
+
// but are otherwise identical.
|
|
25547
|
+
[getLoopLocalName(block, '$index')]: '$index',
|
|
25548
|
+
[block.itemName]: '$item',
|
|
25549
|
+
}, bannedGlobals);
|
|
25550
|
+
const params = [new FnParam('$index'), new FnParam('$item')];
|
|
25551
|
+
const stmts = convertPureComponentScopeFunction(block.trackBy.ast, scope, variable(CONTEXT_NAME), 'track');
|
|
25552
|
+
const usesComponentInstance = scope.getComponentAccessCount() > 0;
|
|
25553
|
+
let fn$1;
|
|
25554
|
+
if (!usesComponentInstance && stmts.length === 1 && stmts[0] instanceof ExpressionStatement) {
|
|
25555
|
+
fn$1 = arrowFn(params, stmts[0].expr);
|
|
25467
25556
|
}
|
|
25468
|
-
|
|
25469
|
-
|
|
25470
|
-
|
|
25557
|
+
else {
|
|
25558
|
+
// The last statement is returned implicitly.
|
|
25559
|
+
if (stmts.length > 0) {
|
|
25560
|
+
const lastStatement = stmts[stmts.length - 1];
|
|
25561
|
+
if (lastStatement instanceof ExpressionStatement) {
|
|
25562
|
+
stmts[stmts.length - 1] = new ReturnStatement(lastStatement.expr);
|
|
25563
|
+
}
|
|
25564
|
+
}
|
|
25565
|
+
fn$1 = fn(params, stmts);
|
|
25566
|
+
}
|
|
25567
|
+
return {
|
|
25568
|
+
expression: this.constantPool.getSharedFunctionReference(fn$1, '_forTrack'),
|
|
25569
|
+
usesComponentInstance,
|
|
25570
|
+
};
|
|
25471
25571
|
}
|
|
25472
25572
|
getConstCount() {
|
|
25473
25573
|
return this._dataIndex;
|
|
@@ -25939,6 +26039,10 @@ class BindingScope {
|
|
|
25939
26039
|
// local var we used to store the component context, e.g. const $comp$ = x();
|
|
25940
26040
|
return this.bindingLevel === 0 ? null : this.getComponentProperty(name);
|
|
25941
26041
|
}
|
|
26042
|
+
/** Checks whether a variable exists locally on the current scope. */
|
|
26043
|
+
hasLocal(name) {
|
|
26044
|
+
return this.map.has(name);
|
|
26045
|
+
}
|
|
25942
26046
|
/**
|
|
25943
26047
|
* Create a local variable for later reference.
|
|
25944
26048
|
*
|
|
@@ -26098,6 +26202,45 @@ class BindingScope {
|
|
|
26098
26202
|
this.usesRestoredViewContext = true;
|
|
26099
26203
|
}
|
|
26100
26204
|
}
|
|
26205
|
+
/** Binding scope of a `track` function inside a `for` loop block. */
|
|
26206
|
+
class TrackByBindingScope extends BindingScope {
|
|
26207
|
+
constructor(parentScope, globalAliases, bannedGlobals) {
|
|
26208
|
+
super(parentScope.bindingLevel + 1, parentScope);
|
|
26209
|
+
this.globalAliases = globalAliases;
|
|
26210
|
+
this.bannedGlobals = bannedGlobals;
|
|
26211
|
+
this.componentAccessCount = 0;
|
|
26212
|
+
}
|
|
26213
|
+
get(name) {
|
|
26214
|
+
let current = this.parent;
|
|
26215
|
+
// Verify that the expression isn't trying to access a variable from a parent scope.
|
|
26216
|
+
while (current) {
|
|
26217
|
+
if (current.hasLocal(name)) {
|
|
26218
|
+
this.forbiddenAccessError(name);
|
|
26219
|
+
}
|
|
26220
|
+
current = current.parent;
|
|
26221
|
+
}
|
|
26222
|
+
// If the variable is one of the banned globals, we have to throw.
|
|
26223
|
+
if (this.bannedGlobals.has(name)) {
|
|
26224
|
+
this.forbiddenAccessError(name);
|
|
26225
|
+
}
|
|
26226
|
+
// Intercept any aliased globals.
|
|
26227
|
+
if (this.globalAliases[name]) {
|
|
26228
|
+
return variable(this.globalAliases[name]);
|
|
26229
|
+
}
|
|
26230
|
+
// When the component scope is accessed, we redirect it through `this`.
|
|
26231
|
+
this.componentAccessCount++;
|
|
26232
|
+
return variable('this').prop(name);
|
|
26233
|
+
}
|
|
26234
|
+
/** Gets the number of times the host component has been accessed through the scope. */
|
|
26235
|
+
getComponentAccessCount() {
|
|
26236
|
+
return this.componentAccessCount;
|
|
26237
|
+
}
|
|
26238
|
+
forbiddenAccessError(propertyName) {
|
|
26239
|
+
// TODO(crisbeto): this should be done through template type checking once it is available.
|
|
26240
|
+
throw new Error(`Accessing ${propertyName} inside of a track expression is not allowed. ` +
|
|
26241
|
+
`Tracking expressions can only access the item, $index and properties on the containing component.`);
|
|
26242
|
+
}
|
|
26243
|
+
}
|
|
26101
26244
|
/**
|
|
26102
26245
|
* Creates a `CssSelector` given a tag name and a map of attributes
|
|
26103
26246
|
*/
|
|
@@ -27803,7 +27946,7 @@ function publishFacade(global) {
|
|
|
27803
27946
|
* @description
|
|
27804
27947
|
* Entry point for all public APIs of the compiler package.
|
|
27805
27948
|
*/
|
|
27806
|
-
const VERSION = new Version('17.0.0-next.
|
|
27949
|
+
const VERSION = new Version('17.0.0-next.3');
|
|
27807
27950
|
|
|
27808
27951
|
class CompilerConfig {
|
|
27809
27952
|
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, useJit = true, missingTranslation = null, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
@@ -29961,7 +30104,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
|
|
|
29961
30104
|
function compileDeclareClassMetadata(metadata) {
|
|
29962
30105
|
const definitionMap = new DefinitionMap();
|
|
29963
30106
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
29964
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
30107
|
+
definitionMap.set('version', literal('17.0.0-next.3'));
|
|
29965
30108
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
29966
30109
|
definitionMap.set('type', metadata.type);
|
|
29967
30110
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -30069,7 +30212,7 @@ function createDirectiveDefinitionMap(meta) {
|
|
|
30069
30212
|
// in 16.1 is actually used.
|
|
30070
30213
|
const minVersion = hasTransformFunctions ? MINIMUM_PARTIAL_LINKER_VERSION$5 : '14.0.0';
|
|
30071
30214
|
definitionMap.set('minVersion', literal(minVersion));
|
|
30072
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
30215
|
+
definitionMap.set('version', literal('17.0.0-next.3'));
|
|
30073
30216
|
// e.g. `type: MyDirective`
|
|
30074
30217
|
definitionMap.set('type', meta.type.value);
|
|
30075
30218
|
if (meta.isStandalone) {
|
|
@@ -30300,7 +30443,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
30300
30443
|
function compileDeclareFactoryFunction(meta) {
|
|
30301
30444
|
const definitionMap = new DefinitionMap();
|
|
30302
30445
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
30303
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
30446
|
+
definitionMap.set('version', literal('17.0.0-next.3'));
|
|
30304
30447
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
30305
30448
|
definitionMap.set('type', meta.type.value);
|
|
30306
30449
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -30335,7 +30478,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
30335
30478
|
function createInjectableDefinitionMap(meta) {
|
|
30336
30479
|
const definitionMap = new DefinitionMap();
|
|
30337
30480
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
30338
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
30481
|
+
definitionMap.set('version', literal('17.0.0-next.3'));
|
|
30339
30482
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
30340
30483
|
definitionMap.set('type', meta.type.value);
|
|
30341
30484
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -30386,7 +30529,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
30386
30529
|
function createInjectorDefinitionMap(meta) {
|
|
30387
30530
|
const definitionMap = new DefinitionMap();
|
|
30388
30531
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
30389
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
30532
|
+
definitionMap.set('version', literal('17.0.0-next.3'));
|
|
30390
30533
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
30391
30534
|
definitionMap.set('type', meta.type.value);
|
|
30392
30535
|
definitionMap.set('providers', meta.providers);
|
|
@@ -30419,7 +30562,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
30419
30562
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
30420
30563
|
}
|
|
30421
30564
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
30422
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
30565
|
+
definitionMap.set('version', literal('17.0.0-next.3'));
|
|
30423
30566
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
30424
30567
|
definitionMap.set('type', meta.type.value);
|
|
30425
30568
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -30470,7 +30613,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
30470
30613
|
function createPipeDefinitionMap(meta) {
|
|
30471
30614
|
const definitionMap = new DefinitionMap();
|
|
30472
30615
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
30473
|
-
definitionMap.set('version', literal('17.0.0-next.
|
|
30616
|
+
definitionMap.set('version', literal('17.0.0-next.3'));
|
|
30474
30617
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
30475
30618
|
// e.g. `type: MyPipe`
|
|
30476
30619
|
definitionMap.set('type', meta.type.value);
|