Skip to content

Conversation

@sagudev
Copy link
Member

@sagudev sagudev commented Oct 31, 2025

Draft because it needs companion PR in servo.

Somehow related to #554, but it creates more strict JSContext.

More concrete documentation is written at types: https://github.com/sagudev/mozjs/blob/cx/mozjs/src/context.rs, here I will only describe rough idea and motivation.

If we want to build any proper safe wrappers we need to have a notion of GC/NoGC, JSContext somehow fulfills the role of GC (generally every SM function that can trigger GC takes JSContext). But to be able to use JSContext (and it's lifetime) for this notion we need to make it not globally obtainable obtainable (it needs to be passed down as an arg as mentioned in https://github.com/asajeffrey/josephine). This is already happening with CanGC we have in servo (this new JSContext would replace CanGC).

This PR also introduce new wrappers that use lifetimed handles and new safe JSContext. More specifically they use &mut JSContext (for functions that can trigger GC) or &JSContext (for functions that cannot trigger GC). We also remove https://doc.servo.org/mozjs/jsapi/struct.AutoRequireNoGC.html from args (as NoGC is already encoded in &JSContext argument).

The plan forward

The idea is that we can incrementally introduce safety to servo:

  • start using and passing down this new JSContext everywhere in servo
  • Handles/Roots would use NoGC to create & of inner data
  • DomRefCell would also take NoGC on borrow, borrow_mut to prevent borrows across GC.
  • I think we could also write part of unrooted with this, when creating unrooted value it would have 'cx lifetime (bounded to cx) and rooting would erase the lifetime (make it 'static thus unbound it from cx).
    • The biggest problems are return values, which also need to be bounded. This will require some additional work in mozjs

Notes on the model

While GC is run only on some compartments/realm, this becomes complicated to model because of cross references. So this model assumes all compartments in cx will get traced/GC (even if that is not the case; but that does happen on full GC I think). This is more strict than per compartments, but much easier to model and reason about (look at how complicated https://github.com/asajeffrey/josephine is). We can always introduced more relaxed model later.

This model is already discussed in #520, #560, #569 and something similar is also used in nova js engine: https://trynova.dev/blog/guide-to-nova-gc (I borrowed idea of explicit NoGC token).

Signed-off-by: sagudev <[email protected]>
@sagudev sagudev changed the title Add safe JSContext wrapper with stritct safety rules Add safe JSContext wrapper with strict safety rules Oct 31, 2025
f
Signed-off-by: sagudev <[email protected]>
Signed-off-by: sagudev <[email protected]>
@sagudev
Copy link
Member Author

sagudev commented Nov 2, 2025

While this model is safe from mozjs POV, the question is how usable it is in servo, where Runtime is always part of some GlobalScope dom_struct. So in practice all entrypoints (where we get initial cx for passdown) will need to be unbounded (unsafe).

Also doc tests are not run in CI and I think we would benefit with DerefMut hatch too.

f
Signed-off-by: sagudev <[email protected]>
@sagudev sagudev mentioned this pull request Nov 3, 2025
Signed-off-by: sagudev <[email protected]>
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.

1 participant