From cbeedb03d4c5c8cb5c45679a74f4e2e224789d62 Mon Sep 17 00:00:00 2001 From: AleksanderBodurri Date: Sun, 21 Sep 2025 16:42:14 -0400 Subject: [PATCH] refactor(devtools): use getRouterInstance to replace manual parsing logic Previously we would look in the DI tree for a token named 'Router' and resolve its value. Now we use the already existing getRouterInstance, which depends on ng global debug APIs to get the router instance of an application. (cherry picked from commit c963569c0eaea24c18106f4ff02723137e733114) --- .../src/lib/client-event-subscribers.ts | 90 ++----------------- 1 file changed, 6 insertions(+), 84 deletions(-) diff --git a/devtools/projects/ng-devtools-backend/src/lib/client-event-subscribers.ts b/devtools/projects/ng-devtools-backend/src/lib/client-event-subscribers.ts index 83d1991566a..57c1e718b01 100644 --- a/devtools/projects/ng-devtools-backend/src/lib/client-event-subscribers.ts +++ b/devtools/projects/ng-devtools-backend/src/lib/client-event-subscribers.ts @@ -188,6 +188,7 @@ const getLatestComponentExplorerViewCallback = const checkForAngularCallback = (messageBus: MessageBus) => () => checkForAngular(messageBus); + const getRoutesCallback = (messageBus: MessageBus) => () => getRoutes(messageBus); const navigateRouteCallback = (messageBus: MessageBus) => (path: string) => { @@ -320,16 +321,7 @@ const getSignalNestedPropertiesCallback = // todo: parse router tree with framework APIs after they are developed const getRoutes = (messageBus: MessageBus) => { - const forest = prepareForestForSerialization( - initializeOrGetDirectiveForestHooks().getIndexedDirectiveForest(), - ngDebugDependencyInjectionApiIsSupported(), - ); - if (forest.length === 0) return; - - const rootInjector = forest[0].resolutionPath?.find((i) => i.name === 'Root'); - if (!rootInjector) return; - - const route = getRouterConfigFromRoot(rootInjector); + const route = getRouterConfigFromRoot(); if (!route) return; const sanitizedRoute = sanitizeRouteData(route); @@ -337,83 +329,13 @@ const getRoutes = (messageBus: MessageBus) => { messageBus.emit('updateRouterTree', [[sanitizedRoute]]); }; -const getSerializedProviderRecords = (injector: SerializedInjector) => { - if (!idToInjector.has(injector.id)) { +const getRouterConfigFromRoot = (): Route | void => { + const router = getRouterInstance(); + if (!router) { return; } - const providerRecords = getInjectorProviders(idToInjector.get(injector.id)!); - const allProviderRecords: SerializedProviderRecord[] = []; - const tokenToRecords: Map = new Map(); - - for (const [index, providerRecord] of providerRecords.entries()) { - const record = serializeProviderRecord(providerRecord, index, injector.type === 'environment'); - allProviderRecords.push(record); - - const records = tokenToRecords.get(providerRecord.token) ?? []; - records.push(record); - tokenToRecords.set(providerRecord.token, records); - } - const serializedProviderRecords: SerializedProviderRecord[] = []; - for (const [token, records] of tokenToRecords.entries()) { - const multiRecords = records.filter((record) => record.multi); - const nonMultiRecords = records.filter((record) => !record.multi); - for (const record of nonMultiRecords) { - serializedProviderRecords.push(record); - } - const [firstMultiRecord] = multiRecords; - if (firstMultiRecord !== undefined) { - // All multi providers will have the same token, so we can just use the first one. - serializedProviderRecords.push({ - token: firstMultiRecord.token, - type: 'multi', - multi: true, - // todo(aleksanderbodurri): implememnt way to differentiate multi providers that - // provided as viewProviders - isViewProvider: firstMultiRecord.isViewProvider, - index: records.map((record) => record.index as number), - }); - } - } - - return serializedProviderRecords; -}; - -const getProviderValue = ( - serializedInjector: SerializedInjector, - serializedProvider: SerializedProviderRecord, -) => { - if (!idToInjector.has(serializedInjector.id)) { - return; - } - - const injector = idToInjector.get(serializedInjector.id)!; - const providerRecords = getInjectorProviders(injector); - - if (typeof serializedProvider.index === 'number') { - const provider = providerRecords[serializedProvider.index]; - return injector.get(provider.token, null, {optional: true}); - } else if (Array.isArray(serializedProvider.index)) { - const provider = serializedProvider.index.map((index) => providerRecords[index]); - return injector.get(provider[0].token, null, {optional: true}); - } else { - return; - } -}; - -const getRouterConfigFromRoot = (injector: SerializedInjector): Route | void => { - const serializedProviderRecords = getSerializedProviderRecords(injector) ?? []; - const routerInstance = serializedProviderRecords.find( - (provider) => provider.token === 'Router', // get the instance of router using token - ); - - if (!routerInstance) { - return; - } - - const routerProvider = getProviderValue(injector, routerInstance); - - return parseRoutes(routerProvider); + return parseRoutes(router); }; const checkForAngular = (messageBus: MessageBus): void => {