How to have private state in embedded deno_core JsRuntime?

I need to either keep a reference in rust to an object I then delete globalThis.__context, but I can't do this since values I get from runtime.handle_scope() are Local and need a mutable reference to runtime, and I don't think I can make them global, since that also requires a mutable reference to runtime to get the isolate. Another option that works would be keeping the state in rust and accessing it through ops, but I'm not sure how to do that either.
{
let mut scope = runtime.handle_scope();
let global = scope.get_current_context().global(&mut scope);

let key = v8::String::new(&mut scope, "__context").unwrap();
let context = deno_core::serde_v8::to_v8(&mut scope, &context)?;
global.set(&mut scope, key.into(), context.into());
};

runtime.execute_script_static("<runtime>", include_str!("runtime.js"))?; // deletes __context
runtime.execute_script_static("<freeze>", include_str!("freeze.js"))?;

let value = runtime.execute_script("<eval>", context.code.into())?; // shouldn't have access to __context
let value = runtime.resolve_value(value).await?;

// get the __context here somehow?
{
let mut scope = runtime.handle_scope();
let global = scope.get_current_context().global(&mut scope);

let key = v8::String::new(&mut scope, "__context").unwrap();
let context = deno_core::serde_v8::to_v8(&mut scope, &context)?;
global.set(&mut scope, key.into(), context.into());
};

runtime.execute_script_static("<runtime>", include_str!("runtime.js"))?; // deletes __context
runtime.execute_script_static("<freeze>", include_str!("freeze.js"))?;

let value = runtime.execute_script("<eval>", context.code.into())?; // shouldn't have access to __context
let value = runtime.resolve_value(value).await?;

// get the __context here somehow?
11 Replies
mmastrac
mmastrac11mo ago
Check out the slot methods on the isolate, which you can get from a handlescope: https://docs.rs/v8/latest/v8/struct.Isolate.html#method.set_slot
Isolate in v8 - Rust
Isolate represents an isolated instance of the V8 engine. V8 isolates have completely separate states. Objects from one isolate must not be used in other isolates. The embedder can create multiple isolates and use them in parallel in multiple threads. An isolate can be entered by at most one thread at any given time. The Locker/Unlocker API...
dicksword_is_breaking_gdpr
Can i access that through JS? I need to take a reference to __context in runtime before i delete it
mmastrac
mmastrac11mo ago
You can't access it through JS directly, but you could create #[op]s that read and write it. You can also just turn a local into a global and stash that -- as long as you don't store it anywhere the JS can't reach it
dicksword_is_breaking_gdpr
Yes I tried to create a global It needs a reference to Isolate, and converting the struct to V8 object needs the scope Both take a reference to &mut runtime
mmastrac
mmastrac11mo ago
Oh, I mean you can create a v8::Global (this is different than context.global(...)) let global = v8::Global::new(&mut scope, local); Then you can stash that global anywhere you like... that'll keep the JS object alive, but inaccessible to JS
mmastrac
mmastrac11mo ago
The open method would then allow you to get access to the underlying object (ie: v8::Global<v8::String> -> &v8::String) https://docs.rs/v8/latest/src/v8/handle.rs.html#209-211
handle.rs - source
Source of the Rust file src/handle.rs.
dicksword_is_breaking_gdpr
Oh, v8::Global accepts a &mut scope
mmastrac
mmastrac11mo ago
Yeah, it's a bit confusing because &mut scope has an as_ref to &mut Isolate
dicksword_is_breaking_gdpr
Yep this seems to work, thanks If I delete __context it can't be recovered from outside the runtime.js file, right?
mmastrac
mmastrac11mo ago
Correct.. it's no longer accessible from JS unless you put it back into a JS global or pass it to a function
dicksword_is_breaking_gdpr
I've been wondering if its possible to somehow extract it by overwriting object prototypes or something like that, which is why i copied freeze_instrinsics.js from node Not sure if there's an actual risk though