Skip to content

Commit 5aa427d

Browse files
committed
feat: improved backend error handling
1 parent fb7ebcd commit 5aa427d

File tree

8 files changed

+146
-85
lines changed

8 files changed

+146
-85
lines changed

packages/app-backend-core/src/app.ts

+31-26
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type AppRecordResolver = (record: AppRecord) => void | Promise<void>
2222
const appRecordPromises = new Map<App, AppRecordResolver[]>()
2323

2424
export async function registerApp (options: AppRecordOptions, ctx: BackendContext) {
25-
return jobs.queue(() => registerAppJob(options, ctx))
25+
return jobs.queue('regiserApp', () => registerAppJob(options, ctx))
2626
}
2727

2828
async function registerAppJob (options: AppRecordOptions, ctx: BackendContext) {
@@ -184,7 +184,7 @@ export async function getAppRecord (app: any, ctx: BackendContext): Promise<AppR
184184
}
185185

186186
export function waitForAppsRegistration () {
187-
return jobs.queue(async () => { /* NOOP */ })
187+
return jobs.queue('waitForAppsRegistrationNoop', async () => { /* NOOP */ })
188188
}
189189

190190
export async function sendApps (ctx: BackendContext) {
@@ -231,32 +231,37 @@ let scanTimeout: any
231231
// eslint-disable-next-line camelcase
232232
export function _legacy_getAndRegisterApps (ctx: BackendContext, clear = false) {
233233
setTimeout(() => {
234-
if (clear) {
235-
// Remove apps that are legacy
236-
ctx.appRecords.forEach(appRecord => {
237-
if (appRecord.meta.Vue) {
238-
removeAppRecord(appRecord, ctx)
239-
}
240-
})
241-
}
234+
try {
235+
if (clear) {
236+
// Remove apps that are legacy
237+
ctx.appRecords.forEach(appRecord => {
238+
if (appRecord.meta.Vue) {
239+
removeAppRecord(appRecord, ctx)
240+
}
241+
})
242+
}
242243

243-
const apps = scan()
244+
const apps = scan()
244245

245-
clearTimeout(scanTimeout)
246-
if (!apps.length) {
247-
scanTimeout = setTimeout(() => _legacy_getAndRegisterApps(ctx), 1000)
248-
}
246+
clearTimeout(scanTimeout)
247+
if (!apps.length) {
248+
scanTimeout = setTimeout(() => _legacy_getAndRegisterApps(ctx), 1000)
249+
}
249250

250-
apps.forEach(app => {
251-
const Vue = hook.Vue
252-
registerApp({
253-
app,
254-
types: {},
255-
version: Vue?.version,
256-
meta: {
257-
Vue,
258-
},
259-
}, ctx)
260-
})
251+
apps.forEach(app => {
252+
const Vue = hook.Vue
253+
registerApp({
254+
app,
255+
types: {},
256+
version: Vue?.version,
257+
meta: {
258+
Vue,
259+
},
260+
}, ctx)
261+
})
262+
} catch (e) {
263+
console.error(`Error scanning for legacy apps:`)
264+
console.error(e)
265+
}
261266
}, 0)
262267
}

packages/app-backend-core/src/highlighter.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ function createOverlay () {
3535
const jobQueue = new JobQueue()
3636

3737
export async function highlight (instance: ComponentInstance, backend: DevtoolsBackend, ctx: BackendContext) {
38-
await jobQueue.queue(async () => {
38+
await jobQueue.queue('highlight', async () => {
3939
if (!instance) return
4040

4141
const bounds = await backend.api.getComponentBounds(instance)
@@ -76,7 +76,7 @@ export async function highlight (instance: ComponentInstance, backend: DevtoolsB
7676
}
7777

7878
export async function unHighlight () {
79-
await jobQueue.queue(async () => {
79+
await jobQueue.queue('unHighlight', async () => {
8080
overlay?.parentNode?.removeChild(overlay)
8181
overlayContent?.parentNode?.removeChild(overlayContent)
8282
currentInstance = null
@@ -149,7 +149,7 @@ let updateTimer
149149
function startUpdateTimer (backend: DevtoolsBackend, ctx: BackendContext) {
150150
stopUpdateTimer()
151151
updateTimer = setInterval(() => {
152-
jobQueue.queue(async () => {
152+
jobQueue.queue('updateOverlay', async () => {
153153
await updateOverlay(backend, ctx)
154154
})
155155
}, 1000 / 30) // 30fps

packages/app-backend-core/src/hook.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export function installHook (target, isIframe = false) {
131131
once (event, fn) {
132132
const on = (...args) => {
133133
this.off(event, on)
134-
fn.apply(this, args)
134+
return fn.apply(this, args)
135135
}
136136
this.on(event, on)
137137
},
@@ -164,7 +164,18 @@ export function installHook (target, isIframe = false) {
164164
if (cbs) {
165165
cbs = cbs.slice()
166166
for (let i = 0, l = cbs.length; i < l; i++) {
167-
cbs[i].apply(this, args)
167+
try {
168+
const result = cbs[i].apply(this, args)
169+
if (typeof result?.catch === 'function') {
170+
result.catch(e => {
171+
console.error(`[Hook] Error in async event handler for ${event} with args:`, args)
172+
console.error(e)
173+
})
174+
}
175+
} catch (e) {
176+
console.error(`[Hook] Error in event handler for ${event} with args:`, args)
177+
console.error(e)
178+
}
168179
}
169180
} else {
170181
this._buffer.push([event, ...args])

packages/app-backend-core/src/index.ts

+61-46
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ async function connect () {
102102

103103
// Apps
104104

105-
hook.on(HookEvents.APP_UNMOUNT, app => {
106-
removeApp(app, ctx)
105+
hook.on(HookEvents.APP_UNMOUNT, async app => {
106+
await removeApp(app, ctx)
107107
})
108108

109109
// Components
@@ -209,22 +209,22 @@ async function connect () {
209209

210210
// Component perf
211211

212-
hook.on(HookEvents.PERFORMANCE_START, (app, uid, vm, type, time) => {
213-
performanceMarkStart(app, uid, vm, type, time, ctx)
212+
hook.on(HookEvents.PERFORMANCE_START, async (app, uid, vm, type, time) => {
213+
await performanceMarkStart(app, uid, vm, type, time, ctx)
214214
})
215215

216-
hook.on(HookEvents.PERFORMANCE_END, (app, uid, vm, type, time) => {
217-
performanceMarkEnd(app, uid, vm, type, time, ctx)
216+
hook.on(HookEvents.PERFORMANCE_END, async (app, uid, vm, type, time) => {
217+
await performanceMarkEnd(app, uid, vm, type, time, ctx)
218218
})
219219

220220
// Highlighter
221221

222-
hook.on(HookEvents.COMPONENT_HIGHLIGHT, instanceId => {
223-
highlight(ctx.currentAppRecord.instanceMap.get(instanceId), ctx.currentAppRecord.backend, ctx)
222+
hook.on(HookEvents.COMPONENT_HIGHLIGHT, async instanceId => {
223+
await highlight(ctx.currentAppRecord.instanceMap.get(instanceId), ctx.currentAppRecord.backend, ctx)
224224
})
225225

226-
hook.on(HookEvents.COMPONENT_UNHIGHLIGHT, () => {
227-
unHighlight()
226+
hook.on(HookEvents.COMPONENT_UNHIGHLIGHT, async () => {
227+
await unHighlight()
228228
})
229229

230230
// Timeline
@@ -260,19 +260,19 @@ async function connect () {
260260
ctx.bridge.send(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_ADD, {})
261261
})
262262

263-
hook.on(HookEvents.CUSTOM_INSPECTOR_SEND_TREE, (inspectorId: string, plugin: Plugin) => {
263+
hook.on(HookEvents.CUSTOM_INSPECTOR_SEND_TREE, async (inspectorId: string, plugin: Plugin) => {
264264
const inspector = getInspector(inspectorId, plugin.descriptor.app, ctx)
265265
if (inspector) {
266-
sendInspectorTree(inspector, ctx)
266+
await sendInspectorTree(inspector, ctx)
267267
} else if (SharedData.debugInfo) {
268268
console.warn(`Inspector ${inspectorId} not found`)
269269
}
270270
})
271271

272-
hook.on(HookEvents.CUSTOM_INSPECTOR_SEND_STATE, (inspectorId: string, plugin: Plugin) => {
272+
hook.on(HookEvents.CUSTOM_INSPECTOR_SEND_STATE, async (inspectorId: string, plugin: Plugin) => {
273273
const inspector = getInspector(inspectorId, plugin.descriptor.app, ctx)
274274
if (inspector) {
275-
sendInspectorState(inspector, ctx)
275+
await sendInspectorState(inspector, ctx)
276276
} else if (SharedData.debugInfo) {
277277
console.warn(`Inspector ${inspectorId} not found`)
278278
}
@@ -289,8 +289,18 @@ async function connect () {
289289

290290
// Plugins
291291

292-
addPreviouslyRegisteredPlugins(ctx)
293-
addQueuedPlugins(ctx)
292+
try {
293+
await addPreviouslyRegisteredPlugins(ctx)
294+
} catch (e) {
295+
console.error(`Error adding previously registered plugins:`)
296+
console.error(e)
297+
}
298+
try {
299+
await addQueuedPlugins(ctx)
300+
} catch (e) {
301+
console.error(`Error adding queued plugins:`)
302+
console.error(e)
303+
}
294304

295305
hook.on(HookEvents.SETUP_DEVTOOLS_PLUGIN, async (pluginDescriptor: PluginDescriptor, setupFn: SetupFunction) => {
296306
await addPlugin({ pluginDescriptor, setupFn }, ctx)
@@ -300,11 +310,11 @@ async function connect () {
300310

301311
// Legacy flush
302312

303-
const handleFlush = debounce(() => {
313+
const handleFlush = debounce(async () => {
304314
if (ctx.currentAppRecord?.backend.options.features.includes(BuiltinBackendFeature.FLUSH)) {
305-
sendComponentTreeData(ctx.currentAppRecord, '_root', ctx.currentAppRecord.componentFilter, null, ctx)
315+
await sendComponentTreeData(ctx.currentAppRecord, '_root', ctx.currentAppRecord.componentFilter, null, ctx)
306316
if (ctx.currentInspectedComponentId) {
307-
sendSelectedComponentData(ctx.currentAppRecord, ctx.currentInspectedComponentId, ctx)
317+
await sendSelectedComponentData(ctx.currentAppRecord, ctx.currentInspectedComponentId, ctx)
308318
}
309319
}
310320
}, 500)
@@ -314,13 +324,18 @@ async function connect () {
314324

315325
// Connect done
316326

317-
addTimelineMarker({
318-
id: 'vue-devtools-init-backend',
319-
time: Date.now(),
320-
label: 'Vue Devtools connected',
321-
color: 0x41B883,
322-
all: true,
323-
}, ctx)
327+
try {
328+
await addTimelineMarker({
329+
id: 'vue-devtools-init-backend',
330+
time: Date.now(),
331+
label: 'Vue Devtools connected',
332+
color: 0x41B883,
333+
all: true,
334+
}, ctx)
335+
} catch (e) {
336+
console.error(`Error while adding devtools connected timeline marker:`)
337+
console.error(e)
338+
}
324339
}
325340

326341
function connectBridge () {
@@ -343,8 +358,8 @@ function connectBridge () {
343358

344359
// Apps
345360

346-
ctx.bridge.on(BridgeEvents.TO_BACK_APP_LIST, () => {
347-
sendApps(ctx)
361+
ctx.bridge.on(BridgeEvents.TO_BACK_APP_LIST, async () => {
362+
await sendApps(ctx)
348363
})
349364

350365
ctx.bridge.on(BridgeEvents.TO_BACK_APP_SELECT, async id => {
@@ -365,18 +380,18 @@ function connectBridge () {
365380

366381
// Components
367382

368-
ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_TREE, ({ instanceId, filter }) => {
383+
ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_TREE, async ({ instanceId, filter }) => {
369384
ctx.currentAppRecord.componentFilter = filter
370-
sendComponentTreeData(ctx.currentAppRecord, instanceId, filter, null, ctx)
371385
subscribe(BridgeSubscriptions.COMPONENT_TREE, { instanceId })
386+
await sendComponentTreeData(ctx.currentAppRecord, instanceId, filter, null, ctx)
372387
})
373388

374-
ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_SELECTED_DATA, (instanceId) => {
375-
sendSelectedComponentData(ctx.currentAppRecord, instanceId, ctx)
389+
ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_SELECTED_DATA, async (instanceId) => {
390+
await sendSelectedComponentData(ctx.currentAppRecord, instanceId, ctx)
376391
})
377392

378-
ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_EDIT_STATE, ({ instanceId, dotPath, type, value, newKey, remove }) => {
379-
editComponentState(instanceId, dotPath, type, { value, newKey, remove }, ctx)
393+
ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_EDIT_STATE, async ({ instanceId, dotPath, type, value, newKey, remove }) => {
394+
await editComponentState(instanceId, dotPath, type, { value, newKey, remove }, ctx)
380395
})
381396

382397
ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_INSPECT_DOM, async ({ instanceId }) => {
@@ -456,12 +471,12 @@ function connectBridge () {
456471

457472
// Highlighter
458473

459-
ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_MOUSE_OVER, instanceId => {
460-
highlight(ctx.currentAppRecord.instanceMap.get(instanceId), ctx.currentAppRecord.backend, ctx)
474+
ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_MOUSE_OVER, async instanceId => {
475+
await highlight(ctx.currentAppRecord.instanceMap.get(instanceId), ctx.currentAppRecord.backend, ctx)
461476
})
462477

463-
ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_MOUSE_OUT, () => {
464-
unHighlight()
478+
ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_MOUSE_OUT, async () => {
479+
await unHighlight()
465480
})
466481

467482
// Component picker
@@ -478,12 +493,12 @@ function connectBridge () {
478493

479494
// Timeline
480495

481-
ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_LAYER_LIST, () => {
482-
sendTimelineLayers(ctx)
496+
ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_LAYER_LIST, async () => {
497+
await sendTimelineLayers(ctx)
483498
})
484499

485-
ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_SHOW_SCREENSHOT, ({ screenshot }) => {
486-
showScreenshot(screenshot, ctx)
500+
ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_SHOW_SCREENSHOT, async ({ screenshot }) => {
501+
await showScreenshot(screenshot, ctx)
487502
})
488503

489504
ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_CLEAR, async () => {
@@ -494,8 +509,8 @@ function connectBridge () {
494509
await sendTimelineEventData(id, ctx)
495510
})
496511

497-
ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_LAYER_LOAD_EVENTS, ({ appId, layerId }) => {
498-
sendTimelineLayerEvents(appId, layerId, ctx)
512+
ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_LAYER_LOAD_EVENTS, async ({ appId, layerId }) => {
513+
await sendTimelineLayerEvents(appId, layerId, ctx)
499514
})
500515

501516
ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_LOAD_MARKERS, async () => {
@@ -504,8 +519,8 @@ function connectBridge () {
504519

505520
// Custom inspectors
506521

507-
ctx.bridge.on(BridgeEvents.TO_BACK_CUSTOM_INSPECTOR_LIST, () => {
508-
sendCustomInspectors(ctx)
522+
ctx.bridge.on(BridgeEvents.TO_BACK_CUSTOM_INSPECTOR_LIST, async () => {
523+
await sendCustomInspectors(ctx)
509524
})
510525

511526
ctx.bridge.on(BridgeEvents.TO_BACK_CUSTOM_INSPECTOR_TREE, async ({ inspectorId, appId, treeFilter }) => {

packages/app-backend-core/src/timeline-screenshot.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ interface Screenshot {
1818
}
1919

2020
export async function showScreenshot (screenshot: Screenshot, ctx: BackendContext) {
21-
await jobQueue.queue(async () => {
21+
await jobQueue.queue('showScreenshot', async () => {
2222
if (screenshot) {
2323
if (!container) {
2424
createElements()

0 commit comments

Comments
 (0)