From 3ccea5ccf5bc4951fa8306b74cd918708229c1dc Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sat, 17 Jul 2021 23:07:27 -0400 Subject: [PATCH] py: Support Node.js 14+ or newer (#16) * py: Support Node.js 14+, fix AsyncTask * py: emitter patches * py: update docs --- HISTORY.md | 3 +++ src/javascript/__init__.py | 29 ++++++++++++++++++++++------- src/javascript/config.py | 2 ++ src/javascript/connection.py | 2 +- src/javascript/js/bridge.js | 9 ++++++++- 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index c9414e9..c52c803 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,6 @@ +## 0.2.4 +* py: Support Node versions 14+ + ## 0.2.3 * py: Add notebook and Google Colab support [#15](https://github.com/extremeheat/JSPyBridge/pull/15) * py: CLI now has a new --update flag to update internal, Node.js dependencies. Now use --clean to reset the package store. diff --git a/src/javascript/__init__.py b/src/javascript/__init__.py index 126bd3a..24d8d94 100644 --- a/src/javascript/__init__.py +++ b/src/javascript/__init__.py @@ -13,6 +13,9 @@ def init(): config.global_jsi = proxy.Proxy(config.executor, 0) atexit.register(config.event_loop.on_exit) + if config.global_jsi.needsNodePatches(): + config.node_emitter_patches = True + init() @@ -34,11 +37,10 @@ def require(name, version=None): globalThis = config.global_jsi.globalThis -def AsyncTask(fn): - fn.is_async_task = True - - def decor(start): - t = config.event_loop.startThread(fn) +def AsyncTask(start=False): + def decor(fn): + fn.is_async_task = True + t = config.event_loop.newTaskThread(fn) if start: t.start() @@ -53,7 +55,17 @@ def decor(start): # you will not be able to off an emitter. def On(emitter, event): # print("On", emitter, event,onEvent) - def decor(fn): + def decor(_fn): + # Once Colab updates to Node 16, we can remove this. + # Here we need to manually add in the `this` argument for consistency in Node versions. + # In JS we could normally just bind `this` but there is no bind in Python. + if config.node_emitter_patches: + def handler(*args, **kwargs): + _fn(emitter, *args, **kwargs) + fn = handler + else: + fn = _fn + emitter.on(event, fn) # We need to do some special things here. Because each Python object # on the JS side is unique, EventEmitter is unable to equality check @@ -77,7 +89,10 @@ def decor(fn): i = hash(fn) def handler(*args, **kwargs): - fn(*args, **kwargs) + if config.node_emitter_patches: + fn(emitter, *args, **kwargs) + else: + fn(*args, **kwargs) del config.event_loop.callbacks[i] emitter.once(event, handler) diff --git a/src/javascript/config.py b/src/javascript/config.py index 94b5816..669f3c3 100644 --- a/src/javascript/config.py +++ b/src/javascript/config.py @@ -7,6 +7,8 @@ global_jsi = None # Currently this breaks GC fast_mode = False +# Whether we need patches for legacy node versions +node_emitter_patches = False if ("DEBUG" in os.environ) and ("jspybridge" in os.getenv("DEBUG")): diff --git a/src/javascript/connection.py b/src/javascript/connection.py index 29ccc10..79ebbee 100644 --- a/src/javascript/connection.py +++ b/src/javascript/connection.py @@ -111,7 +111,7 @@ def com_io(): ) except Exception as e: print( - "--====--\t--====--\n\nBridge failed to spawn JS process!\n\nDo you have Node.js 15 or newer installed? Get it at https://nodejs.org/\n\n--====--\t--====--" + "--====--\t--====--\n\nBridge failed to spawn JS process!\n\nDo you have Node.js 16 or newer installed? Get it at https://nodejs.org/\n\n--====--\t--====--" ) stop() raise e diff --git a/src/javascript/js/bridge.js b/src/javascript/js/bridge.js index f9e1a72..2b653b9 100644 --- a/src/javascript/js/bridge.js +++ b/src/javascript/js/bridge.js @@ -51,7 +51,14 @@ class Bridge { console, require: $require, _require: require, - globalThis + globalThis, + needsNodePatches: () => { + const [major, minor] = process.versions.node.split('.') + if ((major == 14 && minor < 17) || (major == 15)) { // eslint-disable-line + return true + } + return false + } } } this.ipc = ipc