Skip to content

Commit 9e61616

Browse files
crisbetothePunderWoman
authored andcommitted
refactor(compiler): introduce deferred block AST (#51050)
Adds the logic to create `defer`-specific AST nodes from the generic HTML `BlockGroup` and `Block`. The logic for parsing the triggers will be in the next commit. PR Close #51050
1 parent 0623158 commit 9e61616

File tree

16 files changed

+867
-37
lines changed

16 files changed

+867
-37
lines changed

packages/compiler-cli/src/ngtsc/indexer/src/template.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import {AST, ASTWithSource, BoundTarget, ImplicitReceiver, ParseSourceSpan, PropertyRead, PropertyWrite, RecursiveAstVisitor, TmplAstBoundAttribute, TmplAstBoundEvent, TmplAstBoundText, TmplAstElement, TmplAstNode, TmplAstRecursiveVisitor, TmplAstReference, TmplAstTemplate, TmplAstVariable} from '@angular/compiler';
8+
import {AST, ASTWithSource, BoundTarget, ImplicitReceiver, ParseSourceSpan, PropertyRead, PropertyWrite, RecursiveAstVisitor, TmplAstBoundAttribute, TmplAstBoundEvent, TmplAstBoundText, TmplAstDeferredBlock, TmplAstDeferredBlockError, TmplAstDeferredBlockLoading, TmplAstDeferredBlockPlaceholder, TmplAstElement, TmplAstNode, TmplAstRecursiveVisitor, TmplAstReference, TmplAstTemplate, TmplAstVariable} from '@angular/compiler';
99

1010
import {ClassDeclaration, DeclarationNode} from '../../reflection';
1111

@@ -187,6 +187,7 @@ class TemplateVisitor extends TmplAstRecursiveVisitor {
187187
this.visitAll(element.children);
188188
this.visitAll(element.outputs);
189189
}
190+
190191
override visitTemplate(template: TmplAstTemplate) {
191192
const templateIdentifier = this.elementOrTemplateToIdentifier(template);
192193

@@ -200,6 +201,7 @@ class TemplateVisitor extends TmplAstRecursiveVisitor {
200201
this.visitAll(template.children);
201202
this.visitAll(template.references);
202203
}
204+
203205
override visitBoundAttribute(attribute: TmplAstBoundAttribute) {
204206
// If the bound attribute has no value, it cannot have any identifiers in the value expression.
205207
if (attribute.valueSpan === undefined) {
@@ -235,6 +237,25 @@ class TemplateVisitor extends TmplAstRecursiveVisitor {
235237
this.identifiers.add(variableIdentifier);
236238
}
237239

240+
override visitDeferredBlock(deferred: TmplAstDeferredBlock) {
241+
this.visitAll(deferred.children);
242+
deferred.placeholder?.visit(this);
243+
deferred.loading?.visit(this);
244+
deferred.error?.visit(this);
245+
}
246+
247+
override visitDeferredBlockPlaceholder(block: TmplAstDeferredBlockPlaceholder) {
248+
this.visitAll(block.children);
249+
}
250+
251+
override visitDeferredBlockError(block: TmplAstDeferredBlockError) {
252+
this.visitAll(block.children);
253+
}
254+
255+
override visitDeferredBlockLoading(block: TmplAstDeferredBlockLoading) {
256+
this.visitAll(block.children);
257+
}
258+
238259
/** Creates an identifier for a template element or template node. */
239260
private elementOrTemplateToIdentifier(node: TmplAstElement|TmplAstTemplate): ElementIdentifier
240261
|TemplateNodeIdentifier|null {

packages/compiler-cli/src/ngtsc/typecheck/extended/api/api.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {AST, ASTWithSource, ParseSourceSpan, RecursiveAstVisitor, TmplAstBoundAttribute, TmplAstBoundEvent, TmplAstBoundText, TmplAstContent, TmplAstElement, TmplAstIcu, TmplAstNode, TmplAstRecursiveVisitor, TmplAstReference, TmplAstTemplate, TmplAstText, TmplAstTextAttribute, TmplAstVariable} from '@angular/compiler';
9+
import {AST, ASTWithSource, ParseSourceSpan, RecursiveAstVisitor, TmplAstBoundAttribute, TmplAstBoundDeferredTrigger, TmplAstBoundEvent, TmplAstBoundText, TmplAstContent, TmplAstDeferredBlock, TmplAstDeferredBlockError, TmplAstDeferredBlockLoading, TmplAstDeferredBlockPlaceholder, TmplAstDeferredTrigger, TmplAstElement, TmplAstIcu, TmplAstNode, TmplAstRecursiveVisitor, TmplAstReference, TmplAstTemplate, TmplAstText, TmplAstTextAttribute, TmplAstVariable} from '@angular/compiler';
1010
import ts from 'typescript';
1111

1212
import {NgCompilerOptions} from '../../../core/api';
@@ -159,6 +159,34 @@ class TemplateVisitor<Code extends ErrorCode> extends RecursiveAstVisitor implem
159159
}
160160
visitIcu(icu: TmplAstIcu): void {}
161161

162+
163+
visitDeferredBlock(deferred: TmplAstDeferredBlock): void {
164+
this.visitAllNodes(deferred.children);
165+
this.visitAllNodes(deferred.triggers);
166+
this.visitAllNodes(deferred.prefetchTriggers);
167+
deferred.placeholder && this.visit(deferred.placeholder);
168+
deferred.loading && this.visit(deferred.loading);
169+
deferred.error && this.visit(deferred.error);
170+
}
171+
172+
visitDeferredTrigger(trigger: TmplAstDeferredTrigger): void {
173+
if (trigger instanceof TmplAstBoundDeferredTrigger) {
174+
this.visitAst(trigger.value);
175+
}
176+
}
177+
178+
visitDeferredBlockPlaceholder(block: TmplAstDeferredBlockPlaceholder): void {
179+
this.visitAllNodes(block.children);
180+
}
181+
182+
visitDeferredBlockError(block: TmplAstDeferredBlockError): void {
183+
this.visitAllNodes(block.children);
184+
}
185+
186+
visitDeferredBlockLoading(block: TmplAstDeferredBlockLoading): void {
187+
this.visitAllNodes(block.children);
188+
}
189+
162190
getDiagnostics(template: TmplAstNode[]): NgTemplateDiagnostic<Code>[] {
163191
this.diagnostics = [];
164192
this.visitAllNodes(template);

packages/compiler/src/compiler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export {SourceMap} from './output/source_map';
6363
export * from './injectable_compiler_2';
6464
export * from './render3/partial/api';
6565
export * from './render3/view/api';
66-
export {BoundAttribute as TmplAstBoundAttribute, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Content as TmplAstContent, Element as TmplAstElement, Icu as TmplAstIcu, Node as TmplAstNode, RecursiveVisitor as TmplAstRecursiveVisitor, Reference as TmplAstReference, Template as TmplAstTemplate, Text as TmplAstText, TextAttribute as TmplAstTextAttribute, Variable as TmplAstVariable} from './render3/r3_ast';
66+
export {BoundAttribute as TmplAstBoundAttribute, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Content as TmplAstContent, Element as TmplAstElement, Icu as TmplAstIcu, Node as TmplAstNode, RecursiveVisitor as TmplAstRecursiveVisitor, Reference as TmplAstReference, Template as TmplAstTemplate, Text as TmplAstText, TextAttribute as TmplAstTextAttribute, Variable as TmplAstVariable, DeferredBlock as TmplAstDeferredBlock, DeferredBlockPlaceholder as TmplAstDeferredBlockPlaceholder, DeferredBlockLoading as TmplAstDeferredBlockLoading, DeferredBlockError as TmplAstDeferredBlockError, DeferredTrigger as TmplAstDeferredTrigger, BoundDeferredTrigger as TmplAstBoundDeferredTrigger, IdleDeferredTrigger as TmplAstIdleDeferredTrigger, ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger, HoverDeferredTrigger as TmplAstHoverDeferredTrigger, TimerDeferredTrigger as TmplAstTimerDeferredTrigger, InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger, ViewportDeferredTrigger as TmplAstViewportDeferredTrigger} from './render3/r3_ast';
6767
export * from './render3/view/t2_api';
6868
export * from './render3/view/t2_binder';
6969
export {Identifiers as R3Identifiers} from './render3/r3_identifiers';

packages/compiler/src/render3/r3_ast.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,88 @@ export class Element implements Node {
117117
}
118118
}
119119

120+
export abstract class DeferredTrigger implements Node {
121+
constructor(public sourceSpan: ParseSourceSpan) {}
122+
123+
visit<Result>(visitor: Visitor<Result>): Result {
124+
return visitor.visitDeferredTrigger(this);
125+
}
126+
}
127+
128+
export class BoundDeferredTrigger extends DeferredTrigger {
129+
constructor(public value: AST, sourceSpan: ParseSourceSpan) {
130+
super(sourceSpan);
131+
}
132+
}
133+
134+
export class IdleDeferredTrigger extends DeferredTrigger {}
135+
136+
export class ImmediateDeferredTrigger extends DeferredTrigger {}
137+
138+
export class HoverDeferredTrigger extends DeferredTrigger {}
139+
140+
export class TimerDeferredTrigger extends DeferredTrigger {
141+
constructor(public delay: number, sourceSpan: ParseSourceSpan) {
142+
super(sourceSpan);
143+
}
144+
}
145+
146+
export class InteractionDeferredTrigger extends DeferredTrigger {
147+
constructor(public reference: string|null, sourceSpan: ParseSourceSpan) {
148+
super(sourceSpan);
149+
}
150+
}
151+
152+
export class ViewportDeferredTrigger extends DeferredTrigger {
153+
constructor(public reference: string|null, sourceSpan: ParseSourceSpan) {
154+
super(sourceSpan);
155+
}
156+
}
157+
158+
export class DeferredBlockPlaceholder implements Node {
159+
constructor(
160+
public children: Node[], public minimumTime: number|null, public sourceSpan: ParseSourceSpan,
161+
public startSourceSpan: ParseSourceSpan, public endSourceSpan: ParseSourceSpan|null) {}
162+
163+
visit<Result>(visitor: Visitor<Result>): Result {
164+
return visitor.visitDeferredBlockPlaceholder(this);
165+
}
166+
}
167+
168+
export class DeferredBlockLoading implements Node {
169+
constructor(
170+
public children: Node[], public afterTime: number|null, public minimumTime: number|null,
171+
public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan,
172+
public endSourceSpan: ParseSourceSpan|null) {}
173+
174+
visit<Result>(visitor: Visitor<Result>): Result {
175+
return visitor.visitDeferredBlockLoading(this);
176+
}
177+
}
178+
179+
export class DeferredBlockError implements Node {
180+
constructor(
181+
public children: Node[], public sourceSpan: ParseSourceSpan,
182+
public startSourceSpan: ParseSourceSpan, public endSourceSpan: ParseSourceSpan|null) {}
183+
184+
visit<Result>(visitor: Visitor<Result>): Result {
185+
return visitor.visitDeferredBlockError(this);
186+
}
187+
}
188+
189+
export class DeferredBlock implements Node {
190+
constructor(
191+
public children: Node[], public triggers: DeferredTrigger[],
192+
public prefetchTriggers: DeferredTrigger[], public placeholder: DeferredBlockPlaceholder|null,
193+
public loading: DeferredBlockLoading|null, public error: DeferredBlockError|null,
194+
public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan,
195+
public endSourceSpan: ParseSourceSpan|null) {}
196+
197+
visit<Result>(visitor: Visitor<Result>): Result {
198+
return visitor.visitDeferredBlock(this);
199+
}
200+
}
201+
120202
export class Template implements Node {
121203
constructor(
122204
// tagName is the name of the container element, if applicable.
@@ -196,6 +278,11 @@ export interface Visitor<Result = any> {
196278
visitText(text: Text): Result;
197279
visitBoundText(text: BoundText): Result;
198280
visitIcu(icu: Icu): Result;
281+
visitDeferredBlock(deferred: DeferredBlock): Result;
282+
visitDeferredBlockPlaceholder(block: DeferredBlockPlaceholder): Result;
283+
visitDeferredBlockError(block: DeferredBlockError): Result;
284+
visitDeferredBlockLoading(block: DeferredBlockLoading): Result;
285+
visitDeferredTrigger(trigger: DeferredTrigger): Result;
199286
}
200287

201288
export class RecursiveVisitor implements Visitor<void> {
@@ -214,6 +301,23 @@ export class RecursiveVisitor implements Visitor<void> {
214301
visitAll(this, template.references);
215302
visitAll(this, template.variables);
216303
}
304+
visitDeferredBlock(deferred: DeferredBlock): void {
305+
visitAll(this, deferred.triggers);
306+
visitAll(this, deferred.prefetchTriggers);
307+
visitAll(this, deferred.children);
308+
deferred.placeholder?.visit(this);
309+
deferred.loading?.visit(this);
310+
deferred.error?.visit(this);
311+
}
312+
visitDeferredBlockPlaceholder(block: DeferredBlockPlaceholder): void {
313+
visitAll(this, block.children);
314+
}
315+
visitDeferredBlockError(block: DeferredBlockError): void {
316+
visitAll(this, block.children);
317+
}
318+
visitDeferredBlockLoading(block: DeferredBlockLoading): void {
319+
visitAll(this, block.children);
320+
}
217321
visitContent(content: Content): void {}
218322
visitVariable(variable: Variable): void {}
219323
visitReference(reference: Reference): void {}
@@ -223,6 +327,7 @@ export class RecursiveVisitor implements Visitor<void> {
223327
visitText(text: Text): void {}
224328
visitBoundText(text: BoundText): void {}
225329
visitIcu(icu: Icu): void {}
330+
visitDeferredTrigger(trigger: DeferredTrigger): void {}
226331
}
227332

228333

0 commit comments

Comments
 (0)