forked from angular/angular
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(core): better organization of
@defer
runtime code
This commit splits the `render3/instructions/defer.ts` file (that contained most of the runtime code) into smalle r files that are easier to maintain. There are no functional changes in this PR, just organizing code.
- Loading branch information
1 parent
da056a1
commit 659072f
Showing
12 changed files
with
836 additions
and
755 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/*! | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
import {Injector, ɵɵdefineInjectable} from '../di'; | ||
|
||
import {TDeferBlockDetails} from './interfaces'; | ||
|
||
/** | ||
* Registers a cleanup function associated with a prefetching trigger | ||
* of a given defer block. | ||
*/ | ||
export function registerTDetailsCleanup( | ||
injector: Injector, tDetails: TDeferBlockDetails, key: string, cleanupFn: VoidFunction) { | ||
injector.get(DeferBlockCleanupManager).add(tDetails, key, cleanupFn); | ||
} | ||
/** | ||
* Invokes all registered prefetch cleanup triggers | ||
* and removes all cleanup functions afterwards. | ||
*/ | ||
export function invokeTDetailsCleanup(injector: Injector, tDetails: TDeferBlockDetails) { | ||
injector.get(DeferBlockCleanupManager).cleanup(tDetails); | ||
} | ||
/** | ||
* Internal service to keep track of cleanup functions associated | ||
* with defer blocks. This class is used to manage cleanup functions | ||
* created for prefetching triggers. | ||
*/ | ||
export class DeferBlockCleanupManager { | ||
private blocks = new Map<TDeferBlockDetails, Map<string, VoidFunction[]>>(); | ||
|
||
add(tDetails: TDeferBlockDetails, key: string, callback: VoidFunction) { | ||
if (!this.blocks.has(tDetails)) { | ||
this.blocks.set(tDetails, new Map()); | ||
} | ||
const block = this.blocks.get(tDetails)!; | ||
if (!block.has(key)) { | ||
block.set(key, []); | ||
} | ||
const callbacks = block.get(key)!; | ||
callbacks.push(callback); | ||
} | ||
|
||
has(tDetails: TDeferBlockDetails, key: string): boolean { | ||
return !!this.blocks.get(tDetails)?.has(key); | ||
} | ||
|
||
cleanup(tDetails: TDeferBlockDetails) { | ||
const block = this.blocks.get(tDetails); | ||
if (block) { | ||
for (const callbacks of Object.values(block)) { | ||
for (const callback of callbacks) { | ||
callback(); | ||
} | ||
} | ||
this.blocks.delete(tDetails); | ||
} | ||
} | ||
|
||
ngOnDestroy() { | ||
for (const [block] of this.blocks) { | ||
this.cleanup(block); | ||
} | ||
this.blocks.clear(); | ||
} | ||
|
||
/** @nocollapse */ | ||
static ɵprov = /** @pureOrBreakMyCode */ ɵɵdefineInjectable({ | ||
token: DeferBlockCleanupManager, | ||
providedIn: 'root', | ||
factory: () => new DeferBlockCleanupManager(), | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
import {CONTAINER_HEADER_OFFSET, LContainer} from '../render3/interfaces/container'; | ||
import {TNode} from '../render3/interfaces/node'; | ||
import {isLContainer, isLView} from '../render3/interfaces/type_checks'; | ||
import {HEADER_OFFSET, LView, TVIEW} from '../render3/interfaces/view'; | ||
|
||
import {TDeferBlockDetails} from './interfaces'; | ||
import {getTDeferBlockDetails, isTDeferBlockDetails} from './utils'; | ||
|
||
/** | ||
* Defer block instance for testing. | ||
*/ | ||
export interface DeferBlockDetails { | ||
lContainer: LContainer; | ||
lView: LView; | ||
tNode: TNode; | ||
tDetails: TDeferBlockDetails; | ||
} | ||
|
||
/** | ||
* Retrieves all defer blocks in a given LView. | ||
* | ||
* @param lView lView with defer blocks | ||
* @param deferBlocks defer block aggregator array | ||
*/ | ||
export function getDeferBlocks(lView: LView, deferBlocks: DeferBlockDetails[]) { | ||
const tView = lView[TVIEW]; | ||
for (let i = HEADER_OFFSET; i < tView.bindingStartIndex; i++) { | ||
if (isLContainer(lView[i])) { | ||
const lContainer = lView[i]; | ||
// An LContainer may represent an instance of a defer block, in which case | ||
// we store it as a result. Otherwise, keep iterating over LContainer views and | ||
// look for defer blocks. | ||
const isLast = i === tView.bindingStartIndex - 1; | ||
if (!isLast) { | ||
const tNode = tView.data[i] as TNode; | ||
const tDetails = getTDeferBlockDetails(tView, tNode); | ||
if (isTDeferBlockDetails(tDetails)) { | ||
deferBlocks.push({lContainer, lView, tNode, tDetails}); | ||
// This LContainer represents a defer block, so we exit | ||
// this iteration and don't inspect views in this LContainer. | ||
continue; | ||
} | ||
} | ||
for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) { | ||
getDeferBlocks(lContainer[i] as LView, deferBlocks); | ||
} | ||
} else if (isLView(lView[i])) { | ||
// This is a component, enter the `getDeferBlocks` recursively. | ||
getDeferBlocks(lView[i], deferBlocks); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.