Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding objects to a ShadowRealm #1608

Closed
AaronRPrince opened this issue Jul 31, 2023 · 0 comments
Closed

Adding objects to a ShadowRealm #1608

AaronRPrince opened this issue Jul 31, 2023 · 0 comments

Comments

@AaronRPrince
Copy link

After reading through #789 I've been trying to set up a shadow realm to use as an isolated context. It looks like it could work, but I don't see an easy way to dynamically add objects from C#.

// manually writing the object works as expected
var engine = new Engine();
var sr = engine.Realm.Intrinsics.ShadowRealm.Construct();
sr.Evaluate("var obj = { prop: 100 };");

sr.Evaluate("obj.prop + 100");     // output: 200               - expected
engine.Evaluate("obj.prop + 100"); // error: obj is not defined - expected

What I've tried:

// JsObject.ToString() doesn't serialize the object to JSON.
sr.Evaluate($"var obj = {JsObject.FromObject(sr.Engine, new { prop = 100 })};"); // error: unexpected token
// value passing between realms must be callable or primitive
var func = sr.Evaluate("(obj) => obj.prop + 100");
Engine.Invoke(func, new { Prop = 1 }); // error: result is not callable - sort of expected
// this just sets a prop on the ShadowRealm object itself
sr.Set("obj", JsValue.FromObject(sr.Engine, new { prop = 100 })); 

sr.Evaluate("obj.prop + 100");     // error: obj is not defined - expected
engine.Evaluate("obj.prop + 100"); // error: obj is not defined - expected
// both of these set the value in the global realm not the shadow realm
sr.Engine.SetValue("obj", new { prop = 100 });    
sr.Engine.Realm.GlobalObject.Set("obj", JsValue.FromObject(sr.Engine, new { prop = 100 }));

sr.Evaluate("obj.prop + 100");                    // Cross-Realm Error: obj is not defined
engine.Evaluate("obj.prop + 100");                // output: 200

A work around is either manually serializing the object with Json.NET, System.Text.Json, etc. -- or reflecting the internal realm from the ShadowRealm and setting the global state of that:

var realm = (Realm) sr.GetType().GetField("_shadowRealm", BindingFlags.NonPublic | BindingFlags.Instance)!.GetValue(sr);
realm.GlobalObject.Set("obj", JsValue.FromObject(sr.Engine, new { prop = 100 }));

sr.Evaluate("obj.prop + 100");     // output: 200               - works
engine.Evaluate("obj.prop + 100"); // error: obj is not defined - expected

Question
My question is,from the C# side, am I missing a way to add non-primitive values to a ShadowRealm before or after creating it?

Request
If I'm not, my request is to add a SetValue method to ShadowRealm. That would help make it more usable for non-primitive values. I understand that within JavaScript non-callable, non-primitive values can't cross realms, but between JavaScript and C# we should be able to inject dynamic objects when creating a ShadowRealm. Otherwise re-looking at #789 would be nice.

Repository owner locked and limited conversation to collaborators Aug 1, 2023
@lahma lahma converted this issue into discussion #1609 Aug 1, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant