From 1a2bcb2295c8b4e3a398c8ecbd92cce0affaff1d Mon Sep 17 00:00:00 2001 From: splincode Date: Mon, 27 Jul 2026 15:25:52 +0300 Subject: [PATCH] fix(devtools): avoid initializing profiler in production mode Defer the timing hook subscription until the timing API is explicitly enabled. Keep production module loading and development initialization covered by isolated browser test targets. --- .../src/lib/profiling/BUILD.bazel | 15 ++++++++- .../lib/profiling/performance-track.spec.ts | 31 +++++++++++++++++++ .../src/lib/profiling/performance-track.ts | 24 +++++++++++--- 3 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 devtools/projects/ng-devtools-backend/src/lib/profiling/performance-track.spec.ts diff --git a/devtools/projects/ng-devtools-backend/src/lib/profiling/BUILD.bazel b/devtools/projects/ng-devtools-backend/src/lib/profiling/BUILD.bazel index fb96f4c77f1..c72f4a6fdb1 100644 --- a/devtools/projects/ng-devtools-backend/src/lib/profiling/BUILD.bazel +++ b/devtools/projects/ng-devtools-backend/src/lib/profiling/BUILD.bazel @@ -1,4 +1,4 @@ -load("//devtools/tools:defaults.bzl", "ts_project") +load("//devtools/tools:defaults.bzl", "ts_project", "ts_test_library", "zoneless_web_test_suite") package(default_visibility = ["//devtools:__subpackages__"]) @@ -21,3 +21,16 @@ ts_project( "//devtools/projects/protocol", ], ) + +ts_test_library( + name = "performance_track_test_lib", + srcs = ["performance-track.spec.ts"], + deps = [ + ":profiling", + ], +) + +zoneless_web_test_suite( + name = "performance_track_test", + deps = [":performance_track_test_lib"], +) diff --git a/devtools/projects/ng-devtools-backend/src/lib/profiling/performance-track.spec.ts b/devtools/projects/ng-devtools-backend/src/lib/profiling/performance-track.spec.ts new file mode 100644 index 00000000000..4a847045b41 --- /dev/null +++ b/devtools/projects/ng-devtools-backend/src/lib/profiling/performance-track.spec.ts @@ -0,0 +1,31 @@ +/** + * @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 + */ + +describe('performance track', () => { + const globalWithAngularDebugApi = window as unknown as {ng?: unknown}; + let angularDebugApi: unknown; + + beforeEach(() => { + angularDebugApi = globalWithAngularDebugApi.ng; + globalWithAngularDebugApi.ng = {}; + }); + + afterEach(() => { + if (angularDebugApi === undefined) { + delete globalWithAngularDebugApi.ng; + } else { + globalWithAngularDebugApi.ng = angularDebugApi; + } + }); + + it('does not throw an error when initialized in development mode', async () => { + const performanceTrack = await import('./performance-track'); + + expect(() => performanceTrack.enablePerformanceTrack()).not.toThrow(); + }); +}); diff --git a/devtools/projects/ng-devtools-backend/src/lib/profiling/performance-track.ts b/devtools/projects/ng-devtools-backend/src/lib/profiling/performance-track.ts index da9653769cf..8c0dfa14085 100644 --- a/devtools/projects/ng-devtools-backend/src/lib/profiling/performance-track.ts +++ b/devtools/projects/ng-devtools-backend/src/lib/profiling/performance-track.ts @@ -16,9 +16,6 @@ type Method = keyof LifecycleProfile | 'changeDetection' | string; // Performance track global flag. let chromeDevToolsPerformanceTrackEnabled = false; -/** Enable Angular's performance track in the Chrome DevTools profiler. */ -export const enablePerformanceTrack = () => (chromeDevToolsPerformanceTrackEnabled = true); - /** Disable Angular's performance track in the Chrome DevTools profiler. */ export const disablePerformanceTrack = () => (chromeDevToolsPerformanceTrackEnabled = false); @@ -64,7 +61,7 @@ const endMark = (nodeName: string, method: Method) => { } }; -getProfiler().subscribe({ +const timingHooks = { onChangeDetectionStart(component: ComponentInstance): void { if (!performanceTrackEnabled()) { return; @@ -101,4 +98,21 @@ getProfiler().subscribe({ } endMark(getDirectiveName(component), output); }, -}); +}; + +let performanceTrackInitialized = false; + +function initializePerformanceTrack(): void { + if (performanceTrackInitialized) { + return; + } + + getProfiler().subscribe(timingHooks); + performanceTrackInitialized = true; +} + +/** Enable Angular's performance track in the Chrome DevTools profiler. */ +export function enablePerformanceTrack(): void { + initializePerformanceTrack(); + chromeDevToolsPerformanceTrackEnabled = true; +}