diff --git a/frontend/controller/actions/utils.js b/frontend/controller/actions/utils.js index 414410664..b18aaccac 100644 --- a/frontend/controller/actions/utils.js +++ b/frontend/controller/actions/utils.js @@ -67,12 +67,16 @@ export const encryptedAction = ( // are written const finished = enqueueDeferredPromise('encrypted-action') + let retainFailed = false try { // Writing to a contract requires being subscribed to it // Since we're only interested in writing and we don't know whether // we're subscribed or should be, we use an ephemeral retain here that // is undone at the end in a finally block. - await sbp('chelonia/contract/retain', contractID, { ephemeral: true }) + await sbp('chelonia/contract/retain', contractID, { ephemeral: true }).catch(e => { + retainFailed = true + throw e + }) const state = { [contractID]: await sbp('chelonia/latestContractState', contractID) } @@ -141,7 +145,9 @@ export const encryptedAction = ( throw new GIErrorUIRuntimeError(userFacingErrStr, { cause: e }) } finally { finished() - await sbp('chelonia/contract/release', contractID, { ephemeral: true }) + if (!retainFailed) { + await sbp('chelonia/contract/release', contractID, { ephemeral: true }) + } } } } diff --git a/frontend/model/logger.js b/frontend/model/logger.js index e4ad81e71..dfd0399b9 100644 --- a/frontend/model/logger.js +++ b/frontend/model/logger.js @@ -15,6 +15,7 @@ export async function createLogger (config: Object, { getItem, removeItem, setIt }] )) const appLogsFilter: string[] = [] + // Make a copy of 'methods' to prevent reassignment by 'setAppLogsFilter' const consoleProxy = new Proxy({ ...methods }, { get (o, p, r) { return Reflect.has(o, p) ? Reflect.get(o, p, r) : Reflect.get(originalConsole, p, r) diff --git a/shared/domains/chelonia/chelonia.js b/shared/domains/chelonia/chelonia.js index fad0d9b77..ed995c289 100644 --- a/shared/domains/chelonia/chelonia.js +++ b/shared/domains/chelonia/chelonia.js @@ -643,12 +643,8 @@ export default (sbp('sbp/selectors/register', { }, // This selector is defined primarily for ingesting web push notifications, // although it can be used as a general-purpose API to process events received - // from 'external' sources, with 'external' meaning sources not directly - // managed by Chelonia (i.e., the WebSocket connection) - // This API creates some potential asymmetry in terms of how events are ingested. - // However, it adds flexibility for application developers in terms of managing, - // e.g., web push subcriptions, which can be an involved process that in modern - // browsers requires user interaction. + // from other external sources that are not managed by Chelonia itself (i.e. sources + // other than the Chelonia-managed websocket connection and RESTful API). 'chelonia/handleEvent': async function (event: string) { const { contractID } = GIMessage.deserializeHEAD(event) if (self.registration) {