Skip to content

Commit 1877cc1

Browse files
committed
fix(hooks): dispose the intermediate ViewModel wrapper after instance creation
The wrapper is hook-internal and on the experimental backend owns the artboard resolved for DefaultForArtboard sources; without an explicit dispose it lingers until JS GC finalizes it.
1 parent 217b319 commit 1877cc1

1 file changed

Lines changed: 24 additions & 17 deletions

File tree

src/hooks/useViewModelInstanceAsync.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -118,31 +118,38 @@ async function createInstanceAsync(
118118
return { instance: null, needsDispose: false };
119119
}
120120
}
121-
let vmi: ViewModelInstance | undefined;
122-
if (instanceName) {
123-
try {
124-
vmi = await viewModel.createInstanceByNameAsync(instanceName);
125-
} catch (e) {
121+
try {
122+
let vmi: ViewModelInstance | undefined;
123+
if (instanceName) {
124+
try {
125+
vmi = await viewModel.createInstanceByNameAsync(instanceName);
126+
} catch (e) {
127+
return {
128+
instance: null,
129+
needsDispose: false,
130+
error: instanceNotFoundError(instanceName, e),
131+
};
132+
}
133+
} else {
134+
vmi = await viewModel.createDefaultInstanceAsync();
135+
}
136+
if (!vmi && instanceName) {
126137
return {
127138
instance: null,
128139
needsDispose: false,
129-
error: instanceNotFoundError(instanceName, e),
140+
error: instanceNotFoundError(instanceName),
130141
};
131142
}
132-
} else {
133-
vmi = await viewModel.createDefaultInstanceAsync();
134-
}
135-
if (!vmi && instanceName) {
136-
return {
137-
instance: null,
138-
needsDispose: false,
139-
error: instanceNotFoundError(instanceName),
140-
};
143+
return { instance: vmi ?? null, needsDispose: true };
144+
} finally {
145+
// The intermediate ViewModel wrapper is hook-internal; disposing it
146+
// releases the native resources it owns (e.g. the artboard resolved
147+
// for DefaultForArtboard sources on the experimental backend).
148+
callDispose(viewModel);
141149
}
142-
return { instance: vmi ?? null, needsDispose: true };
143150
}
144151

145-
// ViewModel source
152+
// ViewModel source (caller-owned — not disposed here)
146153
let vmi: ViewModelInstance | undefined;
147154
if (instanceName) {
148155
try {

0 commit comments

Comments
 (0)