Skip to content

propagate toJSON lookup exceptions in simd JSON.stringify - #1317

Merged
saulecabrera merged 1 commit into
bytecodealliance:mainfrom
nabeel-dev21:json-stringify-tojson-exception
Oct 23, 2026
Merged

saulecabrera merged 1 commit into
bytecodealliance:mainfrom
nabeel-dev21:json-stringify-tojson-exception

Conversation

@nabeel-dev21

Copy link
Copy Markdown
Contributor

Description of the change

get_to_json in the simd JSON.stringify path looks up the top-level value's toJSON property through a raw JS_GetProperty call and wraps the result with Value::from_raw without checking for JS_EXCEPTION. When the lookup throws, from an accessor like { get toJSON() { throw e } } or a Proxy get trap, the exception tag is simply "not a function", so stringify carries on serialising the object and returns {} or {"a":1} while the thrown error stays pending on the context. Native JSON.stringify propagates the throw.

The lookup now goes through rquickjs' Object::get with PredefinedAtom::ToJSON, which runs the same property access and returns Err(Exception) on a throw, and call_json_stringify propagates that with ?, the path already taken when toJSON itself throws. That also drops the two unsafe blocks. Added a regression test driven from tests/misc.rs covering the accessor and proxy cases; it fails on the unpatched tree and passes with the fix. The nested toJSON/valueOf/toString lookups inside rquickjs-serde have the same shape, but that lives in a separate crate.

Why am I making this change?

A builtin should not silently discard a thrown exception, and leaving it pending on the runtime is a latent source of confusing errors for whatever next reads the context's exception. Fixing it inside the builtin keeps the SIMD implementation matching the native one, which the fuzz target compares against. Lookups that do not throw behave exactly as before. Verified with cargo test -p javy --target=wasm32-wasip1 on the json and --all-features sets, plus clippy with -D warnings on wasip1 and wasip2 for the lib and misc test targets.

Checklist

  • I've updated the default plugin import namespace and incremented the major version of javy-plugin-api if the QuickJS bytecode has changed.
  • I've updated the relevant CHANGELOG files if necessary. Changes to javy-cli, javy-plugin, and javy-plugin-processing do not require updating CHANGELOG files.
  • I've updated the relevant crate versions if necessary. Versioning policy for library crates
  • I've updated documentation including crate documentation if necessary.

@jeffcharles

Copy link
Copy Markdown
Collaborator

FYI it looks like there are merge conflicts with this PR

@nabeel-dev21
nabeel-dev21 force-pushed the json-stringify-tojson-exception branch from e94d3a9 to 4edeb4e Compare October 23, 2026 07:19
@nabeel-dev21

Copy link
Copy Markdown
Contributor Author

Rebased onto main. The conflicts were with #1311 landing in the same changelog section and at the end of tests/misc.rs, so I folded the entry into the existing Fixed list and kept both tests. No change to the fix itself, and the misc tests still pass natively and on wasip1.

@saulecabrera
saulecabrera merged commit a44e4a4 into bytecodealliance:main Oct 23, 2026
4 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.

3 participants