Skip to content
This repository was archived by the owner on May 18, 2026. It is now read-only.

Commit 87b6f8d

Browse files
committed
fix: add error handling and safety checks for MeshV2 menu
1 parent 24f80c9 commit 87b6f8d

1 file changed

Lines changed: 44 additions & 33 deletions

File tree

src/components/menu-bar/menu-bar.jsx

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,9 @@ class MenuBar extends React.Component {
253253
syncMeshV2Domain () {
254254
const extension = this.props.vm.runtime.peripheralExtensions.meshV2;
255255
if (extension && extension.domain !== this.props.meshV2Domain) {
256-
this.props.onSetMeshV2Domain(extension.domain);
256+
if (this.props.onSetMeshV2Domain) {
257+
this.props.onSetMeshV2Domain(extension.domain);
258+
}
257259
}
258260
}
259261
handleExtensionAdded () {
@@ -263,54 +265,63 @@ class MenuBar extends React.Component {
263265
}
264266
}
265267
getMeshV2Status () {
266-
const vm = this.props.vm;
267-
268-
if (!vm) return {loaded: false};
268+
try {
269+
const vm = this.props.vm;
269270

270-
// In Smalruby 3 / Scratch 3, extensionManager is directly on the vm instance
271-
const extensionManager = vm.extensionManager;
272-
if (!extensionManager) {
273-
return {loaded: false};
274-
}
271+
if (!vm) return {loaded: false};
275272

276-
const isLoaded = extensionManager.isExtensionLoaded('meshV2');
277-
278-
if (!isLoaded) {
279-
return {loaded: false};
280-
}
273+
// In Smalruby 3 / Scratch 3, extensionManager is directly on the vm instance
274+
const extensionManager = vm.extensionManager;
275+
if (!extensionManager) {
276+
return {loaded: false};
277+
}
281278

282-
// peripheralExtensions is on vm.runtime
283-
const runtime = vm.runtime;
284-
if (!runtime || !runtime.peripheralExtensions) {
285-
return {loaded: true, connected: false};
286-
}
279+
const isLoaded = extensionManager.isExtensionLoaded('meshV2');
287280

288-
const extension = runtime.peripheralExtensions.meshV2;
281+
if (!isLoaded) {
282+
return {loaded: false};
283+
}
289284

290-
if (!extension) {
291-
return {loaded: true, connected: false};
292-
}
285+
// peripheralExtensions is on vm.runtime
286+
const runtime = vm.runtime;
287+
if (!runtime || !runtime.peripheralExtensions) {
288+
return {loaded: true, connected: false};
289+
}
293290

294-
const connected = extension.connectionState === 'connected';
295-
const message = extension.menuMessage();
291+
const extension = runtime.peripheralExtensions.meshV2;
296292

297-
return {
298-
loaded: true,
299-
connected: connected,
300-
message: message,
301-
icon: connected ? meshConnectedIcon : meshDisconnectedIcon
302-
};
293+
if (!extension) {
294+
return {loaded: true, connected: false};
295+
}
296+
297+
const connected = extension.connectionState === 'connected';
298+
const message = extension.menuMessage();
299+
300+
return {
301+
loaded: true,
302+
connected: connected,
303+
message: message,
304+
icon: connected ? meshConnectedIcon : meshDisconnectedIcon
305+
};
306+
} catch (e) {
307+
console.error('Mesh V2: Error in getMeshV2Status:', e); // eslint-disable-line no-console
308+
return {loaded: false};
309+
}
303310
}
304311
handleMeshV2MenuClick () {
305312
// Close the Mesh V2 menu
306-
this.props.onRequestCloseMeshV2();
313+
if (this.props.onRequestCloseMeshV2) {
314+
this.props.onRequestCloseMeshV2();
315+
}
307316

308317
// Open connection modal
309318
this.props.onOpenConnectionModal('meshV2');
310319
}
311320
handleMeshDomainClick () {
312321
// Close the Mesh V2 menu
313-
this.props.onRequestCloseMeshV2();
322+
if (this.props.onRequestCloseMeshV2) {
323+
this.props.onRequestCloseMeshV2();
324+
}
314325

315326
const extension = this.props.vm.runtime.peripheralExtensions.meshV2;
316327
if (extension && (extension.connectionState === 'connected' || extension.connectionState === 'connecting')) {

0 commit comments

Comments
 (0)