Skip to content

Commit 6c507e7

Browse files
dylhunnalxhub
authored andcommitted
refactor(compiler): Implement defer conditions, and change the way slots are linked (angular#52387)
Previously, we had an "empty shell" implementation of defer conditions, and we used separate ops to represent secondary defer blocks. Now, we have a real scaffolding for supporting the various defer conditions, and the secondary defer block information has been refactored onto the main defer op. Additionally, to enable this, we refactor the way that using slot indices works. Instead of having a trait that causes users of slot indices to be linked to the allocated slot, we share a single `SlotHandle` object by reference. This allows an op to use slot information for more than one Xref at a time, and eliminates a layer of indirection. Co-authored-by: Alex Rickabaugh <[email protected]> PR Close angular#52387
1 parent 225914b commit 6c507e7

25 files changed

+443
-321
lines changed

packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_deferred/TEST_CASES.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
],
1717
"failureMessage": "Incorrect template"
1818
}
19-
]
19+
],
20+
"skipForTemplatePipeline": true
2021
},
2122
{
2223
"description": "should generate a deferred block with secondary blocks",
@@ -33,7 +34,8 @@
3334
],
3435
"failureMessage": "Incorrect template"
3536
}
36-
]
37+
],
38+
"skipForTemplatePipeline": true
3739
},
3840
{
3941
"description": "should generate a deferred block with placeholder block parameters",

packages/compiler/src/template/pipeline/ir/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ export * from './src/ops/create';
1313
export * from './src/ops/host';
1414
export * from './src/ops/shared';
1515
export * from './src/ops/update';
16+
export * from './src/handle';
1617
export * from './src/traits';
1718
export * from './src/variable';

packages/compiler/src/template/pipeline/ir/src/enums.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,3 +507,20 @@ export enum I18nParamValueFlags {
507507
*/
508508
CloseTag = 0b1000,
509509
}
510+
511+
/**
512+
* Whether the active namespace is HTML, MathML, or SVG mode.
513+
*/
514+
export enum Namespace {
515+
HTML,
516+
SVG,
517+
Math,
518+
}
519+
520+
/**
521+
* The type of a `@defer` trigger, for use in the ir.
522+
*/
523+
export enum DeferTriggerKind {
524+
Idle,
525+
Interaction,
526+
}

packages/compiler/src/template/pipeline/ir/src/expression.ts

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import type {ParseSourceSpan} from '../../../../parse_util';
1111

1212
import * as t from '../../../../render3/r3_ast';
1313
import {ExpressionKind, OpKind, SanitizerFn} from './enums';
14-
import {ConsumesVarsTrait, UsesSlotIndex, UsesSlotIndexTrait, UsesVarOffset, UsesVarOffsetTrait} from './traits';
15-
14+
import {ConsumesVarsTrait, UsesVarOffset, UsesVarOffsetTrait} from './traits';
15+
import {SlotHandle} from './handle';
1616
import type {XrefId} from './operations';
1717
import type {CreateOp} from './ops/create';
1818
import {Interpolation, type UpdateOp} from './ops/update';
@@ -90,14 +90,10 @@ export class LexicalReadExpr extends ExpressionBase {
9090
/**
9191
* Runtime operation to retrieve the value of a local reference.
9292
*/
93-
export class ReferenceExpr extends ExpressionBase implements UsesSlotIndexTrait {
93+
export class ReferenceExpr extends ExpressionBase {
9494
override readonly kind = ExpressionKind.Reference;
9595

96-
readonly[UsesSlotIndex] = true;
97-
98-
targetSlot: number|null = null;
99-
100-
constructor(readonly target: XrefId, readonly offset: number) {
96+
constructor(readonly target: XrefId, readonly targetSlot: SlotHandle, readonly offset: number) {
10197
super();
10298
}
10399

@@ -114,9 +110,7 @@ export class ReferenceExpr extends ExpressionBase implements UsesSlotIndexTrait
114110
override transformInternalExpressions(): void {}
115111

116112
override clone(): ReferenceExpr {
117-
const expr = new ReferenceExpr(this.target, this.offset);
118-
expr.targetSlot = this.targetSlot;
119-
return expr;
113+
return new ReferenceExpr(this.target, this.targetSlot, this.offset);
120114
}
121115
}
122116

@@ -442,18 +436,17 @@ export class PureFunctionParameterExpr extends ExpressionBase {
442436
}
443437
}
444438

445-
export class PipeBindingExpr extends ExpressionBase implements UsesSlotIndexTrait,
446-
ConsumesVarsTrait,
439+
export class PipeBindingExpr extends ExpressionBase implements ConsumesVarsTrait,
447440
UsesVarOffsetTrait {
448441
override readonly kind = ExpressionKind.PipeBinding;
449-
readonly[UsesSlotIndex] = true;
450442
readonly[ConsumesVarsTrait] = true;
451443
readonly[UsesVarOffset] = true;
452444

453-
targetSlot: number|null = null;
454445
varOffset: number|null = null;
455446

456-
constructor(readonly target: XrefId, readonly name: string, readonly args: o.Expression[]) {
447+
constructor(
448+
readonly target: XrefId, readonly targetSlot: SlotHandle, readonly name: string,
449+
readonly args: o.Expression[]) {
457450
super();
458451
}
459452

@@ -479,27 +472,24 @@ export class PipeBindingExpr extends ExpressionBase implements UsesSlotIndexTrai
479472
}
480473

481474
override clone() {
482-
const r = new PipeBindingExpr(this.target, this.name, this.args.map(a => a.clone()));
483-
r.targetSlot = this.targetSlot;
475+
const r =
476+
new PipeBindingExpr(this.target, this.targetSlot, this.name, this.args.map(a => a.clone()));
484477
r.varOffset = this.varOffset;
485478
return r;
486479
}
487480
}
488481

489-
export class PipeBindingVariadicExpr extends ExpressionBase implements UsesSlotIndexTrait,
490-
ConsumesVarsTrait,
482+
export class PipeBindingVariadicExpr extends ExpressionBase implements ConsumesVarsTrait,
491483
UsesVarOffsetTrait {
492484
override readonly kind = ExpressionKind.PipeBindingVariadic;
493-
readonly[UsesSlotIndex] = true;
494485
readonly[ConsumesVarsTrait] = true;
495486
readonly[UsesVarOffset] = true;
496487

497-
targetSlot: number|null = null;
498488
varOffset: number|null = null;
499489

500490
constructor(
501-
readonly target: XrefId, readonly name: string, public args: o.Expression,
502-
public numArgs: number) {
491+
readonly target: XrefId, readonly targetSlot: SlotHandle, readonly name: string,
492+
public args: o.Expression, public numArgs: number) {
503493
super();
504494
}
505495

@@ -521,8 +511,8 @@ export class PipeBindingVariadicExpr extends ExpressionBase implements UsesSlotI
521511
}
522512

523513
override clone(): PipeBindingVariadicExpr {
524-
const r = new PipeBindingVariadicExpr(this.target, this.name, this.args.clone(), this.numArgs);
525-
r.targetSlot = this.targetSlot;
514+
const r = new PipeBindingVariadicExpr(
515+
this.target, this.targetSlot, this.name, this.args.clone(), this.numArgs);
526516
r.varOffset = this.varOffset;
527517
return r;
528518
}
@@ -766,31 +756,25 @@ export class SanitizerExpr extends ExpressionBase {
766756
override transformInternalExpressions(): void {}
767757
}
768758

769-
export class SlotLiteralExpr extends ExpressionBase implements UsesSlotIndexTrait {
759+
export class SlotLiteralExpr extends ExpressionBase {
770760
override readonly kind = ExpressionKind.SlotLiteralExpr;
771-
readonly[UsesSlotIndex] = true;
772761

773-
constructor(readonly target: XrefId) {
762+
constructor(readonly slot: SlotHandle) {
774763
super();
775764
}
776765

777-
targetSlot: number|null = null;
778-
779766
override visitExpression(visitor: o.ExpressionVisitor, context: any): any {}
780767

781768
override isEquivalent(e: Expression): boolean {
782-
return e instanceof SlotLiteralExpr && e.target === this.target &&
783-
e.targetSlot === this.targetSlot;
769+
return e instanceof SlotLiteralExpr && e.slot === this.slot;
784770
}
785771

786772
override isConstant() {
787773
return true;
788774
}
789775

790776
override clone(): SlotLiteralExpr {
791-
const copy = new SlotLiteralExpr(this.target);
792-
copy.targetSlot = this.targetSlot;
793-
return copy;
777+
return new SlotLiteralExpr(this.slot);
794778
}
795779

796780
override transformInternalExpressions(): void {}
@@ -805,7 +789,7 @@ export class ConditionalCaseExpr extends ExpressionBase {
805789
* @param target The Xref of the view to be displayed if this condition is true.
806790
*/
807791
constructor(
808-
public expr: o.Expression|null, readonly target: XrefId,
792+
public expr: o.Expression|null, readonly target: XrefId, readonly targetSlot: SlotHandle,
809793
readonly alias: t.Variable|null = null) {
810794
super();
811795
}
@@ -825,7 +809,7 @@ export class ConditionalCaseExpr extends ExpressionBase {
825809
}
826810

827811
override clone(): ConditionalCaseExpr {
828-
return new ConditionalCaseExpr(this.expr, this.target);
812+
return new ConditionalCaseExpr(this.expr, this.target, this.targetSlot);
829813
}
830814

831815
override transformInternalExpressions(transform: ExpressionTransform, flags: VisitorContextFlag):
@@ -975,7 +959,6 @@ export function transformExpressionsInOp(
975959
case OpKind.ContainerStart:
976960
case OpKind.Defer:
977961
case OpKind.DeferOn:
978-
case OpKind.DeferSecondaryBlock:
979962
case OpKind.DisableBindings:
980963
case OpKind.Element:
981964
case OpKind.ElementEnd:
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
export class SlotHandle {
10+
slot: number|null = null;
11+
}

0 commit comments

Comments
 (0)