webassembly: Fix GC tracing of object returned from top-level functions. by dpgeorge · Pull Request #19141 · micropython/micropython · GitHub
Skip to content

webassembly: Fix GC tracing of object returned from top-level functions.#19141

Open
dpgeorge wants to merge 1 commit intomicropython:masterfrom
dpgeorge:webassembly-fix-premature-gc-collection
Open

webassembly: Fix GC tracing of object returned from top-level functions.#19141
dpgeorge wants to merge 1 commit intomicropython:masterfrom
dpgeorge:webassembly-fix-premature-gc-collection

Conversation

@dpgeorge
Copy link
Copy Markdown
Member

Summary

This commit makes sure that the GC explicitly traces the Python object returned from all top-level functions. Without this, it's possible that a JsProxy that is created as the return object is freed on the Python side (and hence the underlying JavaScript object entry set to undefined) just prior to the top-level C function returning. So when it does return and control resumes on the JavaScript side, the JavaScript object corresponding to the JsProxy is gone.

For example, the case covered by the test added here has the return value (Python object) from proxy_c_to_js_call() reclaimed by the Python GC via proxy_js_free_obj() before it can be accessed from the JavaScript side, and so the JavaScript reference in proxy_js_ref is undefined,

Testing

I found this in a web app I'm building, there was some strange behaviour which was traced to the issue fixed here. That web app now behaves correctly with this fix.

Also added a test which triggers the same problem. It'll run in CI.

Trade-offs and Alternatives

There may be other ways to structure the fix, but PR #18021 already fixed a related case, and this PR is extending/improving upon that fix.

Generative AI

I did not use generative AI tools when creating this PR.

This commit makes sure that the GC explicitly traces the Python object
returned from all top-level functions.  Without this, it's possible that a
JsProxy that is created as the return object is freed on the Python side
(and hence the underlying JavaScript object entry set to `undefined`) just
prior to the top-level C function returning.  So when it does return and
control resumes on the JavaScript side, the JavaScript object corresponding
to the JsProxy is gone.

For example, the case covered by the test added here has the return value
(Python object) from `proxy_c_to_js_call()` reclaimed by the Python GC via
`proxy_js_free_obj()` before it can be accessed from the JavaScript side,
and so the JavaScript reference in `proxy_js_ref` is `undefined`,

Signed-off-by: Damien George <damien@micropython.org>
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 23, 2026

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