(thisArg, func, preprocessorFunc)
| 44 | * @param {WrapAsyncPreprocessorFunc} [preprocessorFunc] - modifies the API callback's response |
| 45 | */ |
| 46 | const wrapAsync = (thisArg, func, preprocessorFunc) => ( |
| 47 | (...args) => { |
| 48 | let resolve; |
| 49 | let reject; |
| 50 | /* Using resolve/reject to call API in the scope of this function, not inside Promise, |
| 51 | because an API validation exception is thrown synchronously both in Chrome and FF |
| 52 | so the caller can use try/catch to detect it like we've been doing in icon.js */ |
| 53 | const promise = new SafePromise((_resolve, _reject) => { |
| 54 | resolve = _resolve; |
| 55 | reject = _reject; |
| 56 | }); |
| 57 | // Make the error messages actually useful by capturing a real stack |
| 58 | const stackInfo = new SafeError(`callstack before invoking ${func.name || 'chrome API'}:`); |
| 59 | // A single parameter `result` is fine because we don't use API that return more |
| 60 | const cb = result => { |
| 61 | const runtimeErr = chrome.runtime.lastError; |
| 62 | const err = runtimeErr || ( |
| 63 | preprocessorFunc |
| 64 | ? preprocessorFunc(resolve, result) |
| 65 | : resolve(result) |
| 66 | ); |
| 67 | // Prefer `reject` over `throw` which stops debugger in 'pause on exceptions' mode |
| 68 | if (err) { |
| 69 | if (!runtimeErr) stackInfo[STACK] = `${err[1]}\n${stackInfo[STACK]}`; |
| 70 | stackInfo[MESSAGE] = runtimeErr ? err[MESSAGE] : `${err[0]}`; |
| 71 | stackInfo.isRuntime = !!runtimeErr; |
| 72 | reject(stackInfo); |
| 73 | } |
| 74 | }; |
| 75 | if (process.env.IS_INJECTED) { |
| 76 | safePush(args, cb); /* global safePush */ |
| 77 | try { |
| 78 | safeApply(func, thisArg, args); |
| 79 | } catch (e) { |
| 80 | if (e[MESSAGE] === 'Extension context invalidated.') { |
| 81 | /* global logging */// only used with process.env.IS_INJECTED=content |
| 82 | logging.error(`Please reload the tab to restore ${VIOLENTMONKEY} API for userscripts.`); |
| 83 | } else { |
| 84 | throw e; |
| 85 | } |
| 86 | } |
| 87 | } else { |
| 88 | /* Not process.env.IS_INJECTED */// eslint-disable-next-line no-restricted-syntax |
| 89 | thisArg::func(...args, cb); |
| 90 | } |
| 91 | if (process.env.DEBUG) promise.catch(err => console.warn(args, err?.[MESSAGE] || err)); |
| 92 | return promise; |
| 93 | } |
| 94 | ); |
| 95 | const wrapResponse = (result, error) => { |
| 96 | if (process.env.DEBUG) console[error ? 'warn' : 'log']('sendResponse', error || result); |
| 97 | return [ |
no test coverage detected