Add safe JSContext wrapper with strict safety rules #638
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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,
JSContextsomehow 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 withCanGCwe have in servo (this newJSContextwould replaceCanGC).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&JSContextargument).The plan forward
The idea is that we can incrementally introduce safety to servo:
JSContexteverywhere in servo'cxlifetime (bounded to cx) and rooting would erase the lifetime (make it'staticthus unbound it from cx).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).