Skip to content

webassembly: reuse JsProxy objects where possible and fix bug with lost references#18021

Merged
dpgeorge merged 4 commits into
micropython:masterfrom
dpgeorge:webassembly-reuse-jsproxy-ref
Sep 26, 2025
Merged

webassembly: reuse JsProxy objects where possible and fix bug with lost references#18021
dpgeorge merged 4 commits into
micropython:masterfrom
dpgeorge:webassembly-reuse-jsproxy-ref

Conversation

@dpgeorge

@dpgeorge dpgeorge commented Sep 1, 2025

Copy link
Copy Markdown
Member

Summary

PR #17758 improved equality for JsProxy objects so that, eg, js.Object == js.Object is true.

As mentioned in that PR, a further optimisation is to make identity work, eg js.Object is js.Object should be true (on the Python side).

This PR 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.

Testing

Tested locally using the test suite. A new test is added to cover the bug (see above) and existing tests are updated to test object identity.

Trade-offs and Alternatives

This uses memory to keep track of all JsProxy objects, but that's probably counteracted by the fact that there are now less JsProxy objects lying around, due to reuse.

Performance should be unchanged because the code was already checking for existing JS objects on the JS side. That information is now passed across to the Python side without any extra lookup overhead.

@codecov

codecov Bot commented Sep 1, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.38%. Comparing base (f1b00d6) to head (293bb0e).
⚠️ Report is 4 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #18021   +/-   ##
=======================================
  Coverage   98.38%   98.38%           
=======================================
  Files         171      171           
  Lines       22287    22287           
=======================================
  Hits        21928    21928           
  Misses        359      359           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dpgeorge

dpgeorge commented Sep 1, 2025

Copy link
Copy Markdown
Member Author

@WebReflection FYI

This test is not a PyProxy test, rather it's a JsProxy test.

Signed-off-by: Damien George <damien@micropython.org>
Doing GC calls in the entry path (when JavaScript calls into MicroPython at
the top/outer level) can lead to freeing of objects which are still in use.
This is because the (JavaScript) objects are referenced in the input
arguments to the C functions and they are not yet converted to full proxy
objects and not yet tracked properly by the live-object tracker.

Signed-off-by: Damien George <damien@micropython.org>
Commit ffa98cb improved equality for
`JsProxy` objects so that, eg, `js.Object == js.Object` is true.

As mentioned in micropython#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>
With the parent commit implementing proper identities, this equality check
option is no longer needed.

Signed-off-by: Damien George <damien@micropython.org>
@dpgeorge dpgeorge force-pushed the webassembly-reuse-jsproxy-ref branch from b4c4953 to 293bb0e Compare September 26, 2025 04:11
@dpgeorge dpgeorge merged commit 293bb0e into micropython:master Sep 26, 2025
36 checks passed
@dpgeorge dpgeorge deleted the webassembly-reuse-jsproxy-ref branch September 26, 2025 04:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant