(tabId, source, message, responseTimeoutMs = getContentScriptResponseTimeoutMs(message))
| 337 | } |
| 338 | |
| 339 | function sendTabMessageWithTimeout(tabId, source, message, responseTimeoutMs = getContentScriptResponseTimeoutMs(message)) { |
| 340 | return new Promise((resolve, reject) => { |
| 341 | let settled = false; |
| 342 | const startedAt = Date.now(); |
| 343 | const debugLabel = getMessageDebugLabel(source, message, tabId); |
| 344 | |
| 345 | console.log(LOG_PREFIX, `[sendTabMessageWithTimeout] dispatch ${debugLabel}, timeout=${responseTimeoutMs}ms`); |
| 346 | |
| 347 | const timer = setTimeout(() => { |
| 348 | if (settled) return; |
| 349 | settled = true; |
| 350 | const seconds = Math.ceil(responseTimeoutMs / 1000); |
| 351 | console.warn(LOG_PREFIX, `[sendTabMessageWithTimeout] timeout ${debugLabel} after ${Date.now() - startedAt}ms`); |
| 352 | reject(new Error(`Content script on ${source} did not respond in ${seconds}s. Try refreshing the tab and retry.`)); |
| 353 | }, responseTimeoutMs); |
| 354 | |
| 355 | chrome.tabs.sendMessage(tabId, message) |
| 356 | .then((value) => { |
| 357 | const elapsed = Date.now() - startedAt; |
| 358 | if (settled) return; |
| 359 | settled = true; |
| 360 | clearTimeout(timer); |
| 361 | console.log(LOG_PREFIX, `[sendTabMessageWithTimeout] response ${debugLabel} after ${elapsed}ms: ${summarizeMessageResultForDebug(value)}`); |
| 362 | resolve(value); |
| 363 | }) |
| 364 | .catch((error) => { |
| 365 | const elapsed = Date.now() - startedAt; |
| 366 | if (settled) return; |
| 367 | settled = true; |
| 368 | clearTimeout(timer); |
| 369 | console.warn(LOG_PREFIX, `[sendTabMessageWithTimeout] rejection ${debugLabel} after ${elapsed}ms: ${error?.message || error}`); |
| 370 | reject(error); |
| 371 | }); |
| 372 | }); |
| 373 | } |
| 374 | |
| 375 | function queueCommand(source, message, timeout = 15000) { |
| 376 | return new Promise((resolve, reject) => { |
no test coverage detected