Skip to content

Commit 29b959c

Browse files
AndrewKushniratscott
authored andcommitted
refactor(compiler): add an internal API to check is an element is inside a defer block (#53591)
This commit updates the logic to expose an internal API on the `R3BoundTarget` to check if an element belongs to any defer block. PR Close #53591
1 parent a24b24e commit 29b959c

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

packages/compiler/src/render3/view/t2_api.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,4 +227,9 @@ export interface BoundTarget<DirectiveT extends DirectiveMeta> {
227227
* @param trigger Trigger whose target is being looked up.
228228
*/
229229
getDeferredTriggerTarget(block: DeferredBlock, trigger: DeferredTrigger): Element|null;
230+
231+
/**
232+
* Whether a given node is located in a `@defer` block.
233+
*/
234+
isDeferred(node: Element): boolean;
230235
}

packages/compiler/src/render3/view/t2_binder.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export class R3TargetBinder<DirectiveT extends DirectiveMeta> implements TargetB
5151
TemplateBinder.applyWithScope(target.template, scope);
5252
return new R3BoundTarget(
5353
target, directives, eagerDirectives, bindings, references, expressions, symbols,
54-
nestingLevel, scopedNodeEntities, usedPipes, eagerPipes, deferBlocks);
54+
nestingLevel, scopedNodeEntities, usedPipes, eagerPipes, deferBlocks, scope);
5555
}
5656
}
5757

@@ -68,6 +68,11 @@ class Scope implements Visitor {
6868
*/
6969
readonly namedEntities = new Map<string, Reference|Variable>();
7070

71+
/**
72+
* Set of elements that belong to this scope.
73+
*/
74+
readonly elementsInScope = new Set<Element>();
75+
7176
/**
7277
* Child `Scope`s for immediately nested `ScopedNode`s.
7378
*/
@@ -132,6 +137,8 @@ class Scope implements Visitor {
132137

133138
// Recurse into the `Element`'s children.
134139
element.children.forEach(node => node.visit(this));
140+
141+
this.elementsInScope.add(element);
135142
}
136143

137144
visitTemplate(template: Template) {
@@ -731,7 +738,7 @@ export class R3BoundTarget<DirectiveT extends DirectiveMeta> implements BoundTar
731738
private nestingLevel: Map<ScopedNode, number>,
732739
private scopedNodeEntities: Map<ScopedNode|null, ReadonlySet<Reference|Variable>>,
733740
private usedPipes: Set<string>, private eagerPipes: Set<string>,
734-
private deferredBlocks: Set<DeferredBlock>) {}
741+
private deferredBlocks: Set<DeferredBlock>, private rootScope: Scope) {}
735742

736743
getEntitiesInScope(node: ScopedNode|null): ReadonlySet<Reference|Variable> {
737744
return this.scopedNodeEntities.get(node) ?? new Set();
@@ -785,7 +792,6 @@ export class R3BoundTarget<DirectiveT extends DirectiveMeta> implements BoundTar
785792
return Array.from(this.deferredBlocks);
786793
}
787794

788-
789795
getDeferredTriggerTarget(block: DeferredBlock, trigger: DeferredTrigger): Element|null {
790796
// Only triggers that refer to DOM nodes can be resolved.
791797
if (!(trigger instanceof InteractionDeferredTrigger) &&
@@ -849,6 +855,16 @@ export class R3BoundTarget<DirectiveT extends DirectiveMeta> implements BoundTar
849855
return null;
850856
}
851857

858+
isDeferred(element: Element): boolean {
859+
for (const deferBlock of this.deferredBlocks) {
860+
const scope = this.rootScope.childScopes.get(deferBlock);
861+
if (scope && scope.elementsInScope.has(element)) {
862+
return true;
863+
}
864+
}
865+
return false;
866+
}
867+
852868
/**
853869
* Finds an entity with a specific name in a scope.
854870
* @param rootNode Root node of the scope.

0 commit comments

Comments
 (0)