From 5a2bd1eabf86987ab5641dd4913d3fc2e0ba4ad0 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Wed, 14 Feb 2024 11:42:06 -0500 Subject: [PATCH] javascript: fix handler leak (#121) --- src/javascript/js/bridge.js | 18 +++++++++++++----- src/javascript/js/pyi.js | 4 +--- src/pythonia/Bridge.js | 4 ++-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/javascript/js/bridge.js b/src/javascript/js/bridge.js index f99371c..a891fdd 100644 --- a/src/javascript/js/bridge.js +++ b/src/javascript/js/bridge.js @@ -174,12 +174,12 @@ class Bridge { const v = await this.m[ffid] this.ipc.send({ r, val: v.valueOf() }) } - + async blob (r, ffid) { const v = await this.m[ffid] this.ipc.sendBlob(v, r) } - + async keys (r, ffid) { const v = await this.m[ffid] const keys = Object.getOwnPropertyNames(v) @@ -258,7 +258,7 @@ const ipc = { process.stderr.write(JSON.stringify(data) + '\n') }, sendBlob: (data, r) => { - process.stderr.write('blob!{"r":'+r+',"len":'+data.length+'}!') + process.stderr.write('blob!{"r":' + r + ',"len":' + data.length + '}!') process.stderr.write(data) process.stderr.write('\n') }, @@ -283,7 +283,11 @@ process.stdin.on('data', data => { for (const line of message.split('\n')) { try { var j = JSON.parse(line) } catch (e) { continue } // eslint-disable-line if (j.c === 'pyi') { - handlers[j.r]?.(j) + const handler = handlers[j.r] + if (handler) { + handler(j) + delete handlers[j.r] + } } else { bridge.onMessage(j) } @@ -302,7 +306,11 @@ process.stdin.on('end', () => { for (const line of message.split('\n')) { try { var j = JSON.parse(line) } catch (e) { continue } // eslint-disable-line if (j.c === 'pyi') { - handlers[j.r]?.(j) + const handler = handlers[j.r] + if (handler) { + handler(j) + delete handlers[j.r] + } } else { bridge.onMessage(j) } diff --git a/src/javascript/js/pyi.js b/src/javascript/js/pyi.js index 0206c37..f486e01 100644 --- a/src/javascript/js/pyi.js +++ b/src/javascript/js/pyi.js @@ -137,19 +137,17 @@ class PyBridge { ) { const ffid = ++this.jsi.ffid this.jsi.m[ffid] = v - this.queueForCollection(ffid, v) return { ffid } } } return v }) - const stacktrace = new PythonException(stack) - const resp = await waitFor(resolve => this.com.writeRaw(payload, r, resolve), timeout || REQ_TIMEOUT, () => { throw new BridgeException(`Attempt to access '${stack.join('.')}' failed.`) }) if (resp.key === 'error') { + const stacktrace = new PythonException(stack) stacktrace.setPythonTrace(resp.sig) throw stacktrace } diff --git a/src/pythonia/Bridge.js b/src/pythonia/Bridge.js index c30294d..6441b5f 100644 --- a/src/pythonia/Bridge.js +++ b/src/pythonia/Bridge.js @@ -237,7 +237,7 @@ class Bridge { const ffid = pre.val[r] // Python is the owner of the memory, we borrow a ref to it and once // we're done with it (GC'd), we can ask python to free it - if (made[r] instanceof Promise) throw Error('You did not await a paramater when calling ' + stack.join('.')) + if (made[r] instanceof Promise) throw Error('You did not await a parameter when calling ' + stack.join('.')) this.jsi.m[ffid] = made[r] this.queueForCollection(ffid, made[r]) } @@ -296,7 +296,7 @@ class Bridge { } /** - * This method creates a Python class which proxies overriden entries on the + * This method creates a Python class which proxies overridden entries on the * on the JS side over to JS. Conversely, in JS when a property access * is performed on an object that doesn't exist, it's sent to Python. */