Skip to content

Commit 812355c

Browse files
JoostKjosephperrott
authored andcommitted
perf(core): do not recurse into modules that have already been registered (#39514)
When registering an NgModule based on its id, all transitively imported NgModules are also registered. This commit introduces a visited set to avoid traversing into NgModules that are reachable from multiple import paths multiple times. Fixes #39487 PR Close #39514
1 parent 71d0063 commit 812355c

File tree

2 files changed

+24
-16
lines changed

2 files changed

+24
-16
lines changed

packages/core/src/linker/ng_module_factory_registration.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88

99

1010
import {Type} from '../interface/type';
11-
import {autoRegisterModuleById} from '../render3/definition';
11+
import {autoRegisterModuleById, getNgModuleDef} from '../render3/definition';
1212
import {NgModuleType} from '../render3/ng_module_ref';
13+
import {maybeUnwrapFn} from '../render3/util/misc_utils';
1314
import {stringify} from '../util/stringify';
1415

1516
import {NgModuleFactory} from './ng_module_factory';
@@ -39,20 +40,27 @@ function assertSameOrNotExisting(id: string, type: Type<any>|null, incoming: Typ
3940
}
4041
}
4142

42-
export function registerNgModuleType(ngModuleType: NgModuleType) {
43-
if (ngModuleType.ɵmod.id !== null) {
44-
const id = ngModuleType.ɵmod.id;
45-
const existing = modules.get(id) as NgModuleType | null;
46-
assertSameOrNotExisting(id, existing, ngModuleType);
47-
modules.set(id, ngModuleType);
48-
}
43+
export function registerNgModuleType(ngModuleType: NgModuleType): void {
44+
const visited = new Set<NgModuleType>();
45+
recurse(ngModuleType);
46+
function recurse(ngModuleType: NgModuleType): void {
47+
// The imports array of an NgModule must refer to other NgModules,
48+
// so an error is thrown if no module definition is available.
49+
const def = getNgModuleDef(ngModuleType, /* throwNotFound */ true);
50+
const id = def.id;
51+
if (id !== null) {
52+
const existing = modules.get(id) as NgModuleType | null;
53+
assertSameOrNotExisting(id, existing, ngModuleType);
54+
modules.set(id, ngModuleType);
55+
}
4956

50-
let imports = ngModuleType.ɵmod.imports;
51-
if (imports instanceof Function) {
52-
imports = imports();
53-
}
54-
if (imports) {
55-
imports.forEach(i => registerNgModuleType(i as NgModuleType));
57+
const imports = maybeUnwrapFn(def.imports) as NgModuleType[];
58+
for (const i of imports) {
59+
if (!visited.has(i)) {
60+
visited.add(i);
61+
recurse(i);
62+
}
63+
}
5664
}
5765
}
5866

packages/core/test/render3/providers_spec.ts

Lines changed: 2 additions & 2 deletions
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 {Component as _Component, ComponentFactoryResolver, ElementRef, Injectable as _Injectable, InjectFlags, InjectionToken, InjectorType, Provider, RendererFactory2, Type, ViewContainerRef, ɵNgModuleDef as NgModuleDef, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵinject} from '../../src/core';
9+
import {Component as _Component, ComponentFactoryResolver, ElementRef, Injectable as _Injectable, InjectFlags, InjectionToken, InjectorType, Provider, RendererFactory2, Type, ViewContainerRef, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵinject} from '../../src/core';
1010
import {forwardRef} from '../../src/di/forward_ref';
1111
import {createInjector} from '../../src/di/r3_injector';
1212
import {injectComponentFactoryResolver, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdirectiveInject, ɵɵelement, ɵɵelementEnd, ɵɵelementStart, ɵɵgetInheritedFactory, ɵɵProvidersFeature, ɵɵtext, ɵɵtextInterpolate1} from '../../src/render3/index';
@@ -1092,7 +1092,7 @@ describe('providers', () => {
10921092
{provide: String, useValue: 'From module injector'}
10931093
]
10941094
});
1095-
static ɵmod: NgModuleDef<any> = {bootstrap: []} as any;
1095+
static ɵmod = ɵɵdefineNgModule({type: MyAppModule});
10961096
}
10971097
const myAppModuleFactory = new NgModuleFactory(MyAppModule);
10981098
const ngModuleRef = myAppModuleFactory.create(null);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy