Skip to content

fix: lock onmessage to prevent duplicate message handlers - #25

Merged
paberr merged 4 commits into
paberr:mainfrom
jiangheng90:main
Jul 21, 2026
Merged

fix: lock onmessage to prevent duplicate message handlers#25
paberr merged 4 commits into
paberr:mainfrom
jiangheng90:main

Conversation

@jiangheng90

Copy link
Copy Markdown
Contributor

Problem

wasm-bindgen's mod.default() sets self.onmessage during init.
When wasmworker uses addEventListener('message', ...) for task dispatch,
both handlers fire. The wasm-bindgen handler cannot parse wasmworker's
message format, causing Cannot read properties of undefined (reading 'length').

Fix

Lock the onmessage setter via Object.defineProperty with a no-op
setter after mod.default() completes. Applied to both WORKER_JS
and WORKER_JS_WITH_PRECOMPILED.

Testing

Verified with 4-worker pool running mixed #[webworker_fn] and
#[webworker_channel_fn] tasks. No errors.

wasm-bindgen registers a message handler during mod.default()
initialization. When using addEventListener for task dispatch,
both handlers fire for every postMessage, causing the wasm-bindgen
handler to fail on wasmworker-format messages.

Lock the onmessage setter via Object.defineProperty after init
so that addEventListener remains the sole message dispatch path.

@paberr paberr left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the report and the fix. The placement (after mod.default(), before task dispatch, in both blobs) looks correct. Inline comments below. One more ask:

Could you add a regression test in test/, e.g., a #[wasm_bindgen(start)] fn that registers a conflicting onmessage, asserting tasks still complete?

Longer term I would move task dispatch onto a dedicated MessageChannel port, which
would make wasmworker immune to module handlers in both directions. That would be the more robust fix.

Comment thread src/webworker/js.rs Outdated
Comment thread src/webworker/js.rs Outdated
@jiangheng90

jiangheng90 commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

"This issue arose about a month ago when I was trying to integrate my own crate, draco_decoder use in project with thread pool of wasmworker i. However, the issue is quite old now, and I no longer have a code environment that can reproduce it. Moreover, I had made a series of changes to the JavaScript implementation of draco_decoder before, but those have now been reverted. Currently, I am still maintaining the worker creation on the JavaScript side of draco_decoder myself. So I'm very sorry, but this commit was also written by AI, and I'm not sure if it will be of any use."

@paberr

paberr commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Thanks @jiangheng90. I'll have another look this week!

The init handshake and task dispatch now run on a MessagePort transferred
with the first message to the worker, leaving the worker's global message
channel to the embedded module. This replaces the onmessage lock: module
handlers (onmessage or addEventListener) can no longer interfere with task
dispatch, and module messages posted on the global scope can no longer
reach wasmworker's response callback.

@paberr paberr left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dedicated message port looks good

@paberr
paberr merged commit 16729fc into paberr:main Jul 21, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants