diff --git a/python/pythonmonkey/__init__.py b/python/pythonmonkey/__init__.py index f001c06c..e5d45e54 100644 --- a/python/pythonmonkey/__init__.py +++ b/python/pythonmonkey/__init__.py @@ -1,5 +1,6 @@ # Export public PythonMonkey APIs from .pythonmonkey import * +from .helpers import * from .require import * # Expose the package version @@ -24,4 +25,4 @@ Object.defineProperty(Object.prototype, "keys", keysMethod) Object.defineProperty(Array.prototype, "keys", keysMethod) } -""")(lambda *args: list(args)) +""", { 'filename': __file__, 'fromPythonFrame': True })(lambda *args: list(args)) diff --git a/python/pythonmonkey/helpers.py b/python/pythonmonkey/helpers.py new file mode 100644 index 00000000..8c526bb9 --- /dev/null +++ b/python/pythonmonkey/helpers.py @@ -0,0 +1,58 @@ +# @file helpers.py - Python->JS helpers for PythonMonkey +# - typeof operator wrapper +# - new operator wrapper +# +# @author Wes Garland, wes@distributive.network +# @date July 2023 +# + +from . import pythonmonkey as pm +evalOpts = { 'filename': __file__, 'fromPythonFrame': True } + +def typeof(jsval): + """ + typeof function - wraps JS typeof operator + """ + return pm.eval("""'use strict'; ( +function pmTypeof(jsval) +{ + return typeof jsval; +} + )""", evalOpts)(jsval); + +def new(ctor): + """ + new function - emits function which wraps JS new operator, emitting a lambda which constructs a new + JS object upon invocation. + """ + if (typeof(ctor) == 'string'): + ctor = pm.eval(ctor) + + newCtor = pm.eval("""'use strict'; ( +function pmNewFactory(ctor) +{ + return function newCtor(args) { + args = Array.from(args || []); + return new ctor(...args); + }; +} + )""", evalOpts)(ctor) + return (lambda *args: newCtor(list(args))) + +# List which symbols are exposed to the pythonmonkey module. +__all__ = [ "new", "typeof" ] + +# Add the non-enumerable properties of globalThis which don't collide with pythonmonkey.so as exports: +globalThis = pm.eval('globalThis'); +pmGlobals = vars(pm) + +exports = pm.eval(""" +Object.getOwnPropertyNames(globalThis) +.filter(prop => Object.keys(globalThis).indexOf(prop) === -1); +""", evalOpts) + +for index in range(0, int(exports.length)): + name = exports[index] + if (pmGlobals.get(name) == None): + globals().update({name: globalThis[name]}) + __all__.append(name) diff --git a/python/pythonmonkey/require.py b/python/pythonmonkey/require.py index 561ad459..8ad13a63 100644 --- a/python/pythonmonkey/require.py +++ b/python/pythonmonkey/require.py @@ -352,5 +352,5 @@ def require(moduleIdentifier: str): filename = os.path.join(os.getcwd(), "__main__") # use the CWD instead return createRequire(filename)(moduleIdentifier) -# Restrict what are exposed to the pythonmonkey module. +# Restrict what symbols are exposed to the pythonmonkey module. __all__ = ["globalThis", "require", "createRequire", "runProgramModule"]