mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
Several profiler calls don't have any meaningful instance when producing a profiling event. This commit changes the default instance value to null to sreamline profiler invocations. PR Close #59233
259 lines
8.4 KiB
TypeScript
259 lines
8.4 KiB
TypeScript
/**
|
|
* @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.dev/license
|
|
*/
|
|
|
|
import {ɵProfilerEvent} from '@angular/core';
|
|
|
|
import {getDirectiveHostElement} from '../../directive-forest';
|
|
import {ngDebugClient} from '../../ng-debug-api/ng-debug-api';
|
|
import {runOutsideAngular} from '../../utils';
|
|
import {IdentityTracker, NodeArray} from '../identity-tracker';
|
|
|
|
import {getLifeCycleName, Hooks, Profiler} from './shared';
|
|
|
|
type ProfilerCallback = (
|
|
event: ɵProfilerEvent,
|
|
instanceOrLView: {} | null,
|
|
hookOrListener: any,
|
|
) => void;
|
|
|
|
/** Implementation of Profiler that utilizes framework APIs fire profiler hooks. */
|
|
export class NgProfiler extends Profiler {
|
|
private _tracker = IdentityTracker.getInstance();
|
|
private _callbacks: ProfilerCallback[] = [];
|
|
private _lastDirectiveInstance: {} | null = null;
|
|
|
|
constructor(config: Partial<Hooks> = {}) {
|
|
super(config);
|
|
this._setProfilerCallback(
|
|
(event: ɵProfilerEvent, instanceOrLView: {} | null, hookOrListener: any) => {
|
|
if (this[event] === undefined) {
|
|
return;
|
|
}
|
|
|
|
this[event](instanceOrLView, hookOrListener);
|
|
},
|
|
);
|
|
this._initialize();
|
|
}
|
|
|
|
private _initialize(): void {
|
|
ngDebugClient().ɵsetProfiler(
|
|
(event: ɵProfilerEvent, instanceOrLView: {} | null = null, hookOrListener: any) =>
|
|
this._callbacks.forEach((cb) => cb(event, instanceOrLView, hookOrListener)),
|
|
);
|
|
}
|
|
|
|
private _setProfilerCallback(callback: ProfilerCallback): void {
|
|
this._callbacks.push(callback);
|
|
}
|
|
|
|
override destroy(): void {
|
|
this._tracker.destroy();
|
|
}
|
|
|
|
override onIndexForest(newNodes: NodeArray, removedNodes: NodeArray): void {
|
|
newNodes.forEach((node) => {
|
|
const {directive, isComponent} = node;
|
|
|
|
const position = this._tracker.getDirectivePosition(directive);
|
|
const id = this._tracker.getDirectiveId(directive);
|
|
this._onCreate(directive, getDirectiveHostElement(directive), id, isComponent, position);
|
|
});
|
|
|
|
removedNodes.forEach((node) => {
|
|
const {directive, isComponent} = node;
|
|
|
|
const position = this._tracker.getDirectivePosition(directive);
|
|
const id = this._tracker.getDirectiveId(directive);
|
|
this._onDestroy(directive, getDirectiveHostElement(directive), id, isComponent, position);
|
|
});
|
|
}
|
|
|
|
[ɵProfilerEvent.BootstrapApplicationStart](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.BootstrapApplicationEnd](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.BootstrapComponentStart](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.BootstrapComponentEnd](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.ChangeDetectionStart](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.ChangeDetectionEnd](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.ChangeDetectionSyncStart](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.ChangeDetectionSyncEnd](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.AfterRenderHooksStart](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.AfterRenderHooksEnd](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.ComponentStart](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.ComponentEnd](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.DeferBlockStateStart](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.DeferBlockStateEnd](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.DynamicComponentStart](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.DynamicComponentEnd](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.HostBindingsUpdateStart](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.HostBindingsUpdateEnd](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.TemplateCreateStart](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.TemplateCreateEnd](_directive: any, _hookOrListener: any): void {
|
|
// todo: implement
|
|
return;
|
|
}
|
|
|
|
[ɵProfilerEvent.TemplateUpdateStart](context: any, _hookOrListener: any): void {
|
|
if (!this._inChangeDetection) {
|
|
this._inChangeDetection = true;
|
|
runOutsideAngular(() => {
|
|
Promise.resolve().then(() => {
|
|
this.changeDetection$.next();
|
|
this._inChangeDetection = false;
|
|
});
|
|
});
|
|
}
|
|
|
|
const position = this._tracker.getDirectivePosition(context);
|
|
const id = this._tracker.getDirectiveId(context);
|
|
|
|
// If we can find the position and the ID we assume that this is a component instance.
|
|
// Alternatively, if we can't find the ID or the position, we assume that this is a
|
|
// context of an embedded view (for example, NgForOfContext, NgIfContext, or a custom one).
|
|
if (position !== undefined && id !== undefined) {
|
|
this._lastDirectiveInstance = context;
|
|
}
|
|
|
|
if (id !== undefined && position !== undefined) {
|
|
this._onChangeDetectionStart(context, getDirectiveHostElement(context), id, position);
|
|
return;
|
|
}
|
|
|
|
this._onChangeDetectionStart(
|
|
this._lastDirectiveInstance,
|
|
getDirectiveHostElement(this._lastDirectiveInstance),
|
|
this._tracker.getDirectiveId(this._lastDirectiveInstance),
|
|
this._tracker.getDirectivePosition(this._lastDirectiveInstance),
|
|
);
|
|
}
|
|
|
|
[ɵProfilerEvent.TemplateUpdateEnd](context: any, _hookOrListener: any): void {
|
|
const position = this._tracker.getDirectivePosition(context);
|
|
const id = this._tracker.getDirectiveId(context);
|
|
|
|
if (this._tracker.hasDirective(context) && id !== undefined && position !== undefined) {
|
|
this._onChangeDetectionEnd(context, getDirectiveHostElement(context), id, position);
|
|
return;
|
|
}
|
|
|
|
this._onChangeDetectionEnd(
|
|
this._lastDirectiveInstance,
|
|
getDirectiveHostElement(this._lastDirectiveInstance),
|
|
this._tracker.getDirectiveId(this._lastDirectiveInstance),
|
|
this._tracker.getDirectivePosition(this._lastDirectiveInstance),
|
|
);
|
|
}
|
|
|
|
[ɵProfilerEvent.LifecycleHookStart](directive: any, hook: any): void {
|
|
const id = this._tracker.getDirectiveId(directive);
|
|
const element = getDirectiveHostElement(directive);
|
|
const lifecycleHookName = getLifeCycleName(directive, hook);
|
|
const isComponent = !!this._tracker.isComponent.get(directive);
|
|
|
|
this._onLifecycleHookStart(directive, lifecycleHookName, element, id, isComponent);
|
|
}
|
|
|
|
[ɵProfilerEvent.LifecycleHookEnd](directive: any, hook: any): void {
|
|
const id = this._tracker.getDirectiveId(directive);
|
|
const element = getDirectiveHostElement(directive);
|
|
const lifecycleHookName = getLifeCycleName(directive, hook);
|
|
const isComponent = !!this._tracker.isComponent.get(directive);
|
|
|
|
this._onLifecycleHookEnd(directive, lifecycleHookName, element, id, isComponent);
|
|
}
|
|
|
|
[ɵProfilerEvent.OutputStart](componentOrDirective: any, listener: () => void): void {
|
|
const isComponent = !!this._tracker.isComponent.get(componentOrDirective);
|
|
const node = getDirectiveHostElement(componentOrDirective);
|
|
const id = this._tracker.getDirectiveId(componentOrDirective);
|
|
this._onOutputStart(componentOrDirective, listener.name, node, id, isComponent);
|
|
}
|
|
|
|
[ɵProfilerEvent.OutputEnd](componentOrDirective: any, listener: () => void): void {
|
|
const isComponent = !!this._tracker.isComponent.get(componentOrDirective);
|
|
const node = getDirectiveHostElement(componentOrDirective);
|
|
const id = this._tracker.getDirectiveId(componentOrDirective);
|
|
this._onOutputEnd(componentOrDirective, listener.name, node, id, isComponent);
|
|
}
|
|
}
|