ghost-bridge 0.9.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/extension/background.js +52 -21
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
package/extension/background.js
CHANGED
|
@@ -524,6 +524,23 @@ async function resolveTargetTab(params = {}) {
|
|
|
524
524
|
// attach 互斥锁:防止并发调用 ensureAttached 导致重复 attach / 状态竞态
|
|
525
525
|
let _attachLock = Promise.resolve()
|
|
526
526
|
|
|
527
|
+
// Chrome 对冻结/丢弃/无响应标签页的 debugger 调用可能永不回调。
|
|
528
|
+
// 锁内的每次 debugger 操作都必须带超时,否则一次挂起会让锁永不释放,
|
|
529
|
+
// 所有会话的调试功能整体死锁(list_tabs 等非 debugger 命令不受影响)
|
|
530
|
+
const DBG_ATTACH_TIMEOUT_MS = 10000
|
|
531
|
+
const DBG_ENABLE_TIMEOUT_MS = 8000
|
|
532
|
+
const DBG_DETACH_TIMEOUT_MS = 5000
|
|
533
|
+
|
|
534
|
+
function withTimeout(promise, ms, label) {
|
|
535
|
+
return new Promise((resolve, reject) => {
|
|
536
|
+
const timer = setTimeout(() => reject(new Error(`${label} 超时(${ms}ms),标签页可能已被 Chrome 冻结或无响应`)), ms)
|
|
537
|
+
promise.then(
|
|
538
|
+
(v) => { clearTimeout(timer); resolve(v) },
|
|
539
|
+
(e) => { clearTimeout(timer); reject(e) }
|
|
540
|
+
)
|
|
541
|
+
})
|
|
542
|
+
}
|
|
543
|
+
|
|
527
544
|
async function ensureAttachedSession(params = {}) {
|
|
528
545
|
let _release
|
|
529
546
|
const _prev = _attachLock
|
|
@@ -542,32 +559,44 @@ async function ensureAttachedSession(params = {}) {
|
|
|
542
559
|
const session = getSession(tab.id)
|
|
543
560
|
if (!session.attached) {
|
|
544
561
|
try {
|
|
545
|
-
await chrome.debugger.attach({ tabId: tab.id }, "1.3")
|
|
562
|
+
await withTimeout(chrome.debugger.attach({ tabId: tab.id }, "1.3"), DBG_ATTACH_TIMEOUT_MS, `attach 标签页 ${tab.id}`)
|
|
546
563
|
setBadgeState("on")
|
|
547
564
|
} catch (e) {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
565
|
+
// 本扩展重复 attach 视为成功(幂等):也覆盖超时放弃后迟到的 attach 成功等竞态;
|
|
566
|
+
// 其余错误(如 DevTools 正在调试该标签页)照常抛出
|
|
567
|
+
if (!/^already attached/i.test(String(e && e.message))) {
|
|
568
|
+
if (attachedTabId === tab.id) attachedTabId = null
|
|
569
|
+
if (state.connected) {
|
|
570
|
+
setBadgeState("on")
|
|
571
|
+
} else {
|
|
572
|
+
setBadgeState("att")
|
|
573
|
+
}
|
|
574
|
+
throw e
|
|
553
575
|
}
|
|
554
|
-
throw e
|
|
555
576
|
}
|
|
556
577
|
session.attached = true
|
|
557
578
|
resetDebuggerState(session)
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
579
|
+
try {
|
|
580
|
+
await withTimeout((async () => {
|
|
581
|
+
await chrome.debugger.sendCommand({ tabId: session.tabId }, "Runtime.enable")
|
|
582
|
+
await chrome.debugger.sendCommand({ tabId: session.tabId }, "Log.enable")
|
|
583
|
+
await chrome.debugger.sendCommand({ tabId: session.tabId }, "Console.enable").catch(() => {})
|
|
584
|
+
await chrome.debugger.sendCommand({ tabId: session.tabId }, "Debugger.enable")
|
|
585
|
+
await chrome.debugger.sendCommand({ tabId: session.tabId }, "Profiler.enable")
|
|
586
|
+
await chrome.debugger.sendCommand({ tabId: session.tabId }, "Network.enable").catch(() => {})
|
|
587
|
+
|
|
588
|
+
// Enable auto-attach to sub-targets (iframes, workers) for comprehensive capture
|
|
589
|
+
await chrome.debugger.sendCommand({ tabId: session.tabId }, "Target.setAutoAttach", {
|
|
590
|
+
autoAttach: true,
|
|
591
|
+
waitForDebuggerOnStart: false,
|
|
592
|
+
flatten: true,
|
|
593
|
+
}).catch(() => {})
|
|
594
|
+
})(), DBG_ENABLE_TIMEOUT_MS, `初始化调试器会话 ${session.tabId}`)
|
|
595
|
+
} catch (e) {
|
|
596
|
+
// 初始化阶段挂起/失败:放弃该会话,避免后续命令打到半初始化的调试器上
|
|
597
|
+
await detachSession(session)
|
|
598
|
+
throw e
|
|
599
|
+
}
|
|
571
600
|
}
|
|
572
601
|
attachedTabId = session.tabId
|
|
573
602
|
if (isFocusedDefaultTarget) focusedTabId = session.tabId
|
|
@@ -585,7 +614,9 @@ async function ensureAttached(params = {}) {
|
|
|
585
614
|
async function detachSession(session) {
|
|
586
615
|
if (!session) return
|
|
587
616
|
try {
|
|
588
|
-
if (session.attached)
|
|
617
|
+
if (session.attached) {
|
|
618
|
+
await withTimeout(chrome.debugger.detach({ tabId: session.tabId }), DBG_DETACH_TIMEOUT_MS, `detach 标签页 ${session.tabId}`)
|
|
619
|
+
}
|
|
589
620
|
} catch (e) {
|
|
590
621
|
log(`detach 失败:${e.message}`)
|
|
591
622
|
} finally {
|
package/extension/manifest.json
CHANGED