Skip to content

Commit 106917a

Browse files
crisbetoalxhub
authored andcommitted
fix(core): avoid leaking memory if component throws during creation (#57546)
When we create the LView for a component, we track it in the `TRACKED_LVIEWS` map. It gets untracked when it is destroy, but if it throws during creation, the user won't have access to a `ComponentRef` in order to clean it up. These changes automatically untrack the related LViews if the component couldn't be created. PR Close #57546
1 parent b74b5f0 commit 106917a

File tree

12 files changed

+44
-1
lines changed

12 files changed

+44
-1
lines changed

packages/core/src/render3/component_ref.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ import {debugStringifyTypeForError, stringifyForError} from './util/stringify_ut
8888
import {getComponentLViewByIndex, getNativeByTNode, getTNode} from './util/view_utils';
8989
import {ViewRef} from './view_ref';
9090
import {ChainedInjector} from './chained_injector';
91+
import {unregisterLView} from './interfaces/lview_tracking';
9192

9293
export class ComponentFactoryResolver extends AbstractComponentFactoryResolver {
9394
/**
@@ -333,6 +334,7 @@ export class ComponentFactory<T> extends AbstractComponentFactory<T> {
333334

334335
let component: T;
335336
let tElementNode: TElementNode;
337+
let componentView: LView | null = null;
336338

337339
try {
338340
const rootComponentDef = this.componentDef;
@@ -354,7 +356,7 @@ export class ComponentFactory<T> extends AbstractComponentFactory<T> {
354356
}
355357

356358
const hostTNode = createRootComponentTNode(rootLView, hostRNode);
357-
const componentView = createRootComponentView(
359+
componentView = createRootComponentView(
358360
hostTNode,
359361
hostRNode,
360362
rootComponentDef,
@@ -388,6 +390,14 @@ export class ComponentFactory<T> extends AbstractComponentFactory<T> {
388390
[LifecycleHooksFeature],
389391
);
390392
renderView(rootTView, rootLView, null);
393+
} catch (e) {
394+
// Stop tracking the views if creation failed since
395+
// the consumer won't have a way to dereference them.
396+
if (componentView !== null) {
397+
unregisterLView(componentView);
398+
}
399+
unregisterLView(rootLView);
400+
throw e;
391401
} finally {
392402
leaveView();
393403
}

packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,9 @@
14781478
{
14791479
"name": "uniqueIdCounter"
14801480
},
1481+
{
1482+
"name": "unregisterLView"
1483+
},
14811484
{
14821485
"name": "unwrapRNode"
14831486
},

packages/core/test/bundling/animations/bundle.golden_symbols.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,6 +1553,9 @@
15531553
{
15541554
"name": "uniqueIdCounter"
15551555
},
1556+
{
1557+
"name": "unregisterLView"
1558+
},
15561559
{
15571560
"name": "unwrapRNode"
15581561
},

packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,9 @@
12531253
{
12541254
"name": "uniqueIdCounter"
12551255
},
1256+
{
1257+
"name": "unregisterLView"
1258+
},
12561259
{
12571260
"name": "unwrapRNode"
12581261
},

packages/core/test/bundling/defer/bundle.golden_symbols.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2498,6 +2498,9 @@
24982498
{
24992499
"name": "uniqueIdCounter"
25002500
},
2501+
{
2502+
"name": "unregisterLView"
2503+
},
25012504
{
25022505
"name": "unwrapRNode"
25032506
},

packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1889,6 +1889,9 @@
18891889
{
18901890
"name": "uniqueIdCounter"
18911891
},
1892+
{
1893+
"name": "unregisterLView"
1894+
},
18921895
{
18931896
"name": "untracked"
18941897
},

packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,6 +1871,9 @@
18711871
{
18721872
"name": "uniqueIdCounter"
18731873
},
1874+
{
1875+
"name": "unregisterLView"
1876+
},
18741877
{
18751878
"name": "untracked"
18761879
},

packages/core/test/bundling/hello_world/bundle.golden_symbols.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,9 @@
995995
{
996996
"name": "uniqueIdCounter"
997997
},
998+
{
999+
"name": "unregisterLView"
1000+
},
9981001
{
9991002
"name": "unwrapRNode"
10001003
},

packages/core/test/bundling/hydration/bundle.golden_symbols.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,9 @@
13851385
{
13861386
"name": "uniqueIdCounter"
13871387
},
1388+
{
1389+
"name": "unregisterLView"
1390+
},
13881391
{
13891392
"name": "unwrapRNode"
13901393
},

packages/core/test/bundling/router/bundle.golden_symbols.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,6 +2108,9 @@
21082108
{
21092109
"name": "uniqueIdCounter"
21102110
},
2111+
{
2112+
"name": "unregisterLView"
2113+
},
21112114
{
21122115
"name": "unwrapElementRef"
21132116
},

0 commit comments

Comments
 (0)