Commit ffa98cb014 improved equality for
`JsProxy` objects so that, eg, `js.Object == js.Object` is true.
As mentioned in #17758, a further optimisation is to make identity work in
that case, eg `js.Object is js.Object` should be true (on the Python side).
This commit implements that, by keeping track of all `JsProxy` Python
objects and reusing them where possible: where the underlying JS ref is
equal, ie they point to the same JS object. That reduces memory churn and
gives better identity behaviour of JS objects proxied over to Python.
As part of this, a bug is fixed where JS objects can be freed while there's
still a `JsProxy` referring to that JS object. A test is added for that
exact scenario, and the test now passes.
Signed-off-by: Damien George <damien@micropython.org>
Fixes a bug in the binding of self/this to JavaScript methods.
The new semantics match Pyodide's behaviour, at least for the included
tests.
Signed-off-by: Damien George <damien@micropython.org>
So it's possible to know when an external C function is being called at the
top-level, eg by JavaScript without any intermediate C->JS->C calls.
Signed-off-by: Damien George <damien@micropython.org>
This commit defines a new `JsException` exception type which is used on the
Python side to wrap JavaScript errors. That's then used when a JavaScript
Promise is rejected, and the reason is then converted to a `JsException`
for the Python side to handle.
This new exception is exposed as `jsffi.JsException`.
Signed-off-by: Damien George <damien@micropython.org>
This commit improves the webassembly port by adding:
- Proxying of Python objects to JavaScript with a PyProxy type that lives
on the JavaScript side. PyProxy implements JavaScript Proxy traps such
as has, get, set and ownKeys, to make Python objects have functionality
on the JavaScript side.
- Proxying of JavaScript objects to Python with a JsProxy type that lives
on the Python side. JsProxy passes through calls, attributes,
subscription and iteration from Python to JavaScript.
- A top-level API on the JavaScript side to construct a MicroPython
interpreter instance via `loadMicroPython()`. That function returns an
object that can be used to execute Python code, access the Python globals
dict, access the Emscripten filesystem, and other things. This API is
based on the API provided by Pyodide (https://pyodide.org/). As part of
this, the top-level file is changed from `micropython.js` to
`micropython.mjs`.
- A Python `js` module which can be used to access all JavaScript-side
symbols, for example the DOM when run within a browser.
- A Python `jsffi` module with various helper functions like
`create_proxy()` and `to_js()`.
- A dedenting lexer which automatically dedents Python source code if every
non-empty line in that source starts with a common whitespace prefix.
This is very helpful when Python source code is indented within a string
within HTML or JavaScript for formatting reasons.
Signed-off-by: Damien George <damien@micropython.org>